PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » HTTP запрос - несколько вопросов


HTTP запрос - несколько вопросов

Сообщений 1 страница 13 из 13

1

Здравствуйте!
Нужно организовать HTTP запросы. Возникли вопросы, просьба подсказать знающим.
1. ReceiveNetworkData не получает одной командой всю информацию с сайта. Я сделал цикл с проверкой в ответах на закрывающий документ тег </HTML>. Это работает, но ведь это костыль? Какое тут верное решение должно быть? Можно было бы парсить заголовок в ответе, но он далеко не всегда содержит количество передаваемых данных.
2. Как работать с сайтом на HTTPS?
3. Как принимать UTF-8? В примере кода ниже как раз сайт на такой кодировке. Вместо кириллицы кракозябры.

Код:
Procedure$ net_connection (server_name$, method$, webpage$, post$)
; server_name$- домен сайта
; method$ - GET или POST
; webpage$ - имя страницы включая полный путь от домена
; post$ - какие данные отправить странице 
  ConnectionID = OpenNetworkConnection(server_name$, 80)
  If ConnectionID ; соединение произошло
    request$  = method$+" " + webpage$ + " HTTP/1.1" + Chr(13) + Chr(10)
    request$  + "Host: " + server_name$ + Chr(13) + Chr(10) 
    request$  + "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021204" + Chr(13) + Chr(10)
    request$  + "Accept: text/xml,application/xml,application/xhtml+xml," 
    request$  + "text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png," 
    request$  + "image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1" + Chr(13) + Chr(10) 
    request$  + "Accept-Language: en-us, en;q=0.50" + Chr(13) + Chr(10) 
;    request$  + "Accept-Encoding: gzip, deflate, compress;q=0.9" + Chr(13) + Chr(10) 
    request$  + "Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66" + Chr(13) + Chr(10) 
    request$  + "Keep-Alive: 300" + Chr(13) + Chr(10) 
    request$  + "Connection: keep-alive" + Chr(13) + Chr(10) 
    request$  + "Referer: " + referer$ + Chr(13) + Chr(10) 
    request$  + "Cache-Control: max-age=0" + Chr(13) + Chr(10) 
    request$  + "Content-Type: application/x-www-form-urlencoded" + Chr(13) + Chr(10)
    request$  + "Content-Length: " + Str(Len(post$)) + Chr(13) + Chr(10) 
    request$  + Chr(13) + Chr(10) 
    request$  + post$

  res_send = SendNetworkData(ConnectionID,@request$,Len(request$)) 
;Debug "res_send: "+Str(res_send)
  ret$=""
  done.a=0
  bytes_rec=0
  page_len=20000
  timeout=1000
  *mem_buf=AllocateMemory (page_len)
  If Not *mem_buf
    ProcedureReturn "ERROR: memory is not available"
  EndIf
    Repeat 
      Delay(10) 
      Result = NetworkClientEvent(ConnectionID)  
      Select Result 
        Case #PB_NetworkEvent_Data 
          bytes_rec_a=ReceiveNetworkData(ConnectionID, *mem_buf+bytes_rec, page_len) 
          bytes_rec+bytes_rec_a
Debug bytes_rec_a
          If FindString(PeekS (*mem_buf), "</html>", 1) Or FindString(PeekS (*mem_buf), "</HTML>", 1)
            done=1
          ElseIf (MemorySize (*mem_buf)-bytes_rec)<page_len
            *mem_buf=ReAllocateMemory (*mem_buf, MemorySize (*mem_buf)+page_len)
          EndIf
        Case 0
        timeout-1
        If timeout=0
          ret$="ERROR: timeout"+Chr(13)
          Break
        EndIf
      EndSelect 
    Until done = 1
    CloseNetworkConnection(ConnectionID) 
    ret$+PeekS (*mem_buf)
    FreeMemory (*mem_buf)
Debug "bytes_rec: "+Str(bytes_rec)
    ProcedureReturn ret$
  Else; соединение не произошло
    ProcedureReturn "ERROR: no connection"
  EndIf

EndProcedure

InitNetwork()
Enumeration
#win_0
#gad_edit_0
EndEnumeration
win_id=OpenWindow(#win_0, 0, 0, 600, 600, "NET", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)
gad_edit_0_id = EditorGadget(#gad_edit_0, 5, 5, 590, 590)
page_content$=net_connection ("ulyanovskstiralmash.plp7.ru", "GET", "/", "")
SetGadgetText (#gad_edit_0, GetGadgetText(#gad_edit_0)+page_content$)
AddGadgetItem(#gad_edit_0, -1, "___________________"+#CRLF$+"Total: "+Str(Len(page_content$))+" characters")
SendMessage_(GadgetID(#gad_edit_0),#EM_SETSEL,-1,-1)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
End

0

2

Код:
ret$+PeekS (*mem_buf)

попробовать PeekS в другом формате...

0

3

Код:
Procedure$ net_connection (server_name$, method, webpage$, post$)
  ; server_name$- домен сайта
  ; method$ - GET или POST
  ; webpage$ - имя страницы включая полный путь от домена
  ; post$ - какие данные отправить странице 
  NewMap Header$()
  Header$("Content-Type") = "application/x-www-form-urlencoded"
  Header$("UserAgent") = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021204"
  HttpRequest = HTTPRequest(method, server_name$+webpage$, "", 0, Header$())
  If HttpRequest
    Debug "StatusCode: " + HTTPInfo(HTTPRequest, #PB_HTTP_StatusCode)
    ;Debug "Response: " + HTTPInfo(HTTPRequest, #PB_HTTP_Response)
    ProcedureReturn HTTPInfo(HTTPRequest, #PB_HTTP_Response)
    FinishHTTP(HTTPRequest)
  Else
    Debug "Request creation failed"
  EndIf
EndProcedure

InitNetwork()
Enumeration
  #win_0
  #gad_edit_0
EndEnumeration
win_id=OpenWindow(#win_0, 0, 0, 600, 600, "NET", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)
gad_edit_0_id = EditorGadget(#gad_edit_0, 5, 5, 590, 590)
page_content$=net_connection ("http://ulyanovskstiralmash.plp7.ru", #PB_HTTP_Get, "/", "")
SetGadgetText (#gad_edit_0, GetGadgetText(#gad_edit_0)+page_content$)
AddGadgetItem(#gad_edit_0, -1, "___________________"+#CRLF$+"Total: "+Str(Len(page_content$))+" characters")
SendMessage_(GadgetID(#gad_edit_0),#EM_SETSEL,-1,-1)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
End

а так не подходит?

0

4

AZJIO, признаться, я упустил этот момент... Но всё-равно, параметр #PB_UTF8 не помог. С ним вместо кириллицы просто знаки вопроса.

0

5

Lin, нет, не подходит, к сожалению  :( Видимо, моя версия (4.41) старовата для этих функций. А менять свой код в 25000 строк под последнюю версию для меня трудоёмкая задача... o.O

0

6

Timon написал(а):

моя версия (4.41)

такую "мелочь" в первую очередь надо указывать

Код:
#INTERNET_DEFAULT_HTTP_PORT = 80
#INTERNET_DEFAULT_HTTPS_PORT = 443

#INTERNET_OPEN_TYPE_DIRECT = 1
#INTERNET_OPEN_TYPE_PROXY = 3

#INTERNET_SERVICE_HTTP = 3

#INTERNET_FLAG_PRAGMA_NOCACHE =           $00000100
#INTERNET_FLAG_IGNORE_CERT_CN_INVALID =   $00001000
#INTERNET_FLAG_IGNORE_CERT_DATE_INVALID = $00002000
#INTERNET_FLAG_NO_COOKIES =               $00080000
#INTERNET_FLAG_NO_AUTO_REDIRECT =         $00200000
#INTERNET_FLAG_SECURE =                   $00800000
#INTERNET_FLAG_DONT_CACHE =               $04000000

#HTTP_ADDREQ_FLAG_ADD =     $20000000
#HTTP_ADDREQ_FLAG_REPLACE = $80000000

#ERROR_INTERNET_INVALID_CA = 12045

#INTERNET_OPTION_SECURITY_FLAGS = 31

#SECURITY_FLAG_IGNORE_UNKNOWN_CA = $00000100

Procedure.s do_request(fullurl.s, post_data.s="",  cookie.s="", user_agent.s="", referer.s="", proxy.s="", timeout.l=1000, redirect.i=#True)
  
  Protected.l flags, bytes_read, dwFlags, dwBuffLen
  Protected.i is_secure, open_handle, port, connect_handle, request_handle, send_handle, Ok, access_type, LastError
  Protected.s host, page, verb, headers, buffer, result
  Protected.l chunksize=1024
  
  host = GetURLPart(fullurl, #PB_URL_Site)
  page = GetURLPart(fullurl, #PB_URL_Path) + "?" +GetURLPart(fullurl, #PB_URL_Parameters)
     
  If GetURLPart(fullurl, #PB_URL_Protocol) = "http"  : is_secure.i=#False : EndIf
  If GetURLPart(fullurl, #PB_URL_Protocol) = "https" : is_secure.i=#True  : EndIf
  If proxy = "" : access_type =  #INTERNET_OPEN_TYPE_DIRECT : Else : access_type = #INTERNET_OPEN_TYPE_PROXY : EndIf
  If user_agent = "" : user_agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)" : EndIf
  open_handle = InternetOpen_(user_agent, access_type, "", "", 0)
  
  InternetSetOption_(open_handle, 2, timeout, 4)
  flags = #INTERNET_FLAG_PRAGMA_NOCACHE
  flags | #INTERNET_FLAG_NO_COOKIES
  flags | #INTERNET_FLAG_DONT_CACHE
  
  If is_secure
    port = #INTERNET_DEFAULT_HTTPS_PORT
    flags | #INTERNET_FLAG_SECURE
    flags | #INTERNET_FLAG_IGNORE_CERT_CN_INVALID
    flags | #INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
  Else
    port = #INTERNET_DEFAULT_HTTP_PORT
  EndIf
  connect_handle = InternetConnect_(open_handle, host, port, "", "", #INTERNET_SERVICE_HTTP, 0, 0)
  If Not redirect : flags | #INTERNET_FLAG_NO_AUTO_REDIRECT : EndIf
  If post_data = "" : verb = "GET" : Else : verb = "POST" : EndIf
 If page = "" : page = "/" : EndIf
  request_handle = HttpOpenRequest_(connect_handle, verb, page, "", referer, #Null, flags, 0)
  If verb = "POST"
    headers = "Content-Type: text/html" + #CRLF$
    HttpAddRequestHeaders_(request_handle, headers, Len(headers), #HTTP_ADDREQ_FLAG_ADD | #HTTP_ADDREQ_FLAG_REPLACE)
  EndIf
  If cookie <> ""
    headers = "Cookie: "+ cookie + #CRLF$
    HttpAddRequestHeaders_(request_handle, headers, Len(headers), #HTTP_ADDREQ_FLAG_ADD | #HTTP_ADDREQ_FLAG_REPLACE)
  EndIf
  
  Ok = 0
  Repeat
    send_handle = HttpSendRequest_(request_handle, #Null, 0, post_data, Len(post_data))
    
    If send_handle = 0
      LastError = GetLastError_()
      Debug "Error " + Str(LastError)
      If LastError = #ERROR_INTERNET_INVALID_CA
        dwBuffLen = SizeOf(dwFlags)
        InternetQueryOption_(request_handle, #INTERNET_OPTION_SECURITY_FLAGS, @dwFlags, @dwBuffLen)
        dwFlags | #SECURITY_FLAG_IGNORE_UNKNOWN_CA
        InternetSetOption_(request_handle, #INTERNET_OPTION_SECURITY_FLAGS, @dwFlags, SizeOf(dwFlags))
        Ok + 1
      Else
        Ok = 2
      EndIf
    Else
      Ok = 2
    EndIf
  Until Ok = 2
  
  *chunk= AllocateMemory(chunksize)
  Repeat
    InternetReadFile_(request_handle, *chunk, chunksize, @bytes_read)
    result + PeekS(*chunk, bytes_read, #PB_UTF8|#PB_ByteLength)
  Until bytes_read = 0
  FreeMemory(*chunk)
  InternetCloseHandle_(open_handle)
  InternetCloseHandle_(connect_handle)
  InternetCloseHandle_(request_handle)
  InternetCloseHandle_(send_handle)
  ProcedureReturn result
EndProcedure

Debug do_request("http://ulyanovskstiralmash.plp7.ru")

адаптация под старую версию своими силами...

Отредактировано Lin (23.06.2022 01:37:36)

+1

7

Lin, у меня компил ругается на константу #PB_ByteLength. Если её убрать, то результат тот же - вопросы вместо русского текста.

0

8

Lin написал(а):

адаптация под старую версию своими силами...

Lin, спасибо. Ваш код решает 1-й и 2-й мои вопросы, но по прежнему я не могу получить текс кириллицей.

0

9

Timon
На Win10x64 я получаю русский текст.
Использовал регулярное выражение (заменить на ничего)

Код:
(?i)[a-zа-яё;:'"\\\|\(\)\{\}\[\]\^\$~!@#%&\*\-_\d\s\?<>=/~`,.\+]+

чтобы удалить все символы, были там несколько квадратов - нечитаемых символов, но русский текст весь был и там его много.

0

10

Timon
ну не получается с памятью разобраться - попробуй с файлом

Код:
#INTERNET_DEFAULT_HTTP_PORT = 80
#INTERNET_DEFAULT_HTTPS_PORT = 443

#INTERNET_OPEN_TYPE_DIRECT = 1
#INTERNET_OPEN_TYPE_PROXY = 3

#INTERNET_SERVICE_HTTP = 3

#INTERNET_FLAG_PRAGMA_NOCACHE =           $00000100
#INTERNET_FLAG_IGNORE_CERT_CN_INVALID =   $00001000
#INTERNET_FLAG_IGNORE_CERT_DATE_INVALID = $00002000
#INTERNET_FLAG_NO_COOKIES =               $00080000
#INTERNET_FLAG_NO_AUTO_REDIRECT =         $00200000
#INTERNET_FLAG_SECURE =                   $00800000
#INTERNET_FLAG_DONT_CACHE =               $04000000

#HTTP_ADDREQ_FLAG_ADD =     $20000000
#HTTP_ADDREQ_FLAG_REPLACE = $80000000

#ERROR_INTERNET_INVALID_CA = 12045

#INTERNET_OPTION_SECURITY_FLAGS = 31

#SECURITY_FLAG_IGNORE_UNKNOWN_CA = $00000100

Procedure.s do_request_to_file(fullurl.s, post_data.s="",  cookie.s="", user_agent.s="", referer.s="", proxy.s="", timeout.l=1000, redirect.i=#True)
  
  Protected.l flags, bytes_read, dwFlags, dwBuffLen
  Protected.i is_secure, open_handle, port, connect_handle, request_handle, send_handle, Ok, access_type, LastError
  Protected.s host, page, verb, headers, buffer, result
  Protected.l chunksize=1024
  
  host = GetURLPart(fullurl, #PB_URL_Site)
  page = GetURLPart(fullurl, #PB_URL_Path) + "?" +GetURLPart(fullurl, #PB_URL_Parameters)
     
  If GetURLPart(fullurl, #PB_URL_Protocol) = "http"  : is_secure.i=#False : EndIf
  If GetURLPart(fullurl, #PB_URL_Protocol) = "https" : is_secure.i=#True  : EndIf
  If proxy = "" : access_type =  #INTERNET_OPEN_TYPE_DIRECT : Else : access_type = #INTERNET_OPEN_TYPE_PROXY : EndIf
  If user_agent = "" : user_agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)" : EndIf
  open_handle = InternetOpen_(user_agent, access_type, "", "", 0)
  
  InternetSetOption_(open_handle, 2, timeout, 4)
  flags = #INTERNET_FLAG_PRAGMA_NOCACHE
  flags | #INTERNET_FLAG_NO_COOKIES
  flags | #INTERNET_FLAG_DONT_CACHE
  
  If is_secure
    port = #INTERNET_DEFAULT_HTTPS_PORT
    flags | #INTERNET_FLAG_SECURE
    flags | #INTERNET_FLAG_IGNORE_CERT_CN_INVALID
    flags | #INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
  Else
    port = #INTERNET_DEFAULT_HTTP_PORT
  EndIf
  connect_handle = InternetConnect_(open_handle, host, port, "", "", #INTERNET_SERVICE_HTTP, 0, 0)
  If Not redirect : flags | #INTERNET_FLAG_NO_AUTO_REDIRECT : EndIf
  If post_data = "" : verb = "GET" : Else : verb = "POST" : EndIf
 If page = "" : page = "/" : EndIf
  request_handle = HttpOpenRequest_(connect_handle, verb, page, "", referer, #Null, flags, 0)
  If verb = "POST"
    headers = "Content-Type: text/html" + #CRLF$
    HttpAddRequestHeaders_(request_handle, headers, Len(headers), #HTTP_ADDREQ_FLAG_ADD | #HTTP_ADDREQ_FLAG_REPLACE)
  EndIf
  If cookie <> ""
    headers = "Cookie: "+ cookie + #CRLF$
    HttpAddRequestHeaders_(request_handle, headers, Len(headers), #HTTP_ADDREQ_FLAG_ADD | #HTTP_ADDREQ_FLAG_REPLACE)
  EndIf
  
  Ok = 0
  Repeat
    send_handle = HttpSendRequest_(request_handle, #Null, 0, post_data, Len(post_data))
    
    If send_handle = 0
      LastError = GetLastError_()
      Debug "Error " + Str(LastError)
      If LastError = #ERROR_INTERNET_INVALID_CA
        dwBuffLen = SizeOf(dwFlags)
        InternetQueryOption_(request_handle, #INTERNET_OPTION_SECURITY_FLAGS, @dwFlags, @dwBuffLen)
        dwFlags | #SECURITY_FLAG_IGNORE_UNKNOWN_CA
        InternetSetOption_(request_handle, #INTERNET_OPTION_SECURITY_FLAGS, @dwFlags, SizeOf(dwFlags))
        Ok + 1
      Else
        Ok = 2
      EndIf
    Else
      Ok = 2
    EndIf
  Until Ok = 2

  TempFile$ = GetTemporaryDirectory() + Str( Random(50000)) + ".tmp"
  hFile = CreateFile(#PB_Any, TempFile$)
  *chunk= AllocateMemory(chunksize)
  Repeat
    InternetReadFile_(request_handle, *chunk, chunksize, @bytes_read)
    WriteData(hFile, *chunk, bytes_read)
  Until bytes_read = 0
  FreeMemory(*chunk)
  CloseFile(hFile)
  InternetCloseHandle_(open_handle)
  InternetCloseHandle_(connect_handle)
  InternetCloseHandle_(request_handle)
  InternetCloseHandle_(send_handle)
  ProcedureReturn TempFile$
EndProcedure

filename$ =  do_request_to_file("http://ulyanovskstiralmash.plp7.ru")
If ReadFile(0, filename$)   ; if the file could be read, we continue...
  While Eof(0) = 0          ; loop as long the 'end of file' isn't reached
    Debug ReadString(0, #PB_UTF8)      ; display line by line in the debug window
  Wend
  CloseFile(0)               ; close the previously opened file
Else
  MessageRequester("Information","Couldn't open the file!")
EndIf

DeleteFile(filename$)

0

11

Lin, работает, но только если компилировать в юникоде, хотя в справке написано, что можно и так и так:
#PB_UTF8   : Reads the string as UTF8 (the program can be either in unicode or ascii mode)
Но опять же, есть пропуски в виде квадратиков.
Ну да ладно, это пока оставим. Другой вопрос - как получить заголовок от сервера?
Типа этого:

HTTP/1.1 200 OK
  Date: Fri, 21 Mar 2008 09:49:30 GMT
  Server: Apache/1.3.34 (Debian) mod_vhost_online/1.1 mod_fastcgi/2.4.2 mod_log_online/0.1
  X-Powered-By: PHP/4.4.8-1
  Content-Type: text/html

0

12

Timon написал(а):

Другой вопрос - как получить заголовок от сервера?

Потратить вечерок и адаптировать свой код на свежую версию пурика.. а то придумывать с нуля функи, которые уже лет семь в пурике есть - ну вообще не прикольно.

ну и "хинт": завернуть нужные функи из свежего пурика в dll и заюзать эту библиотеку в своём старом коде..  :D

0

13

Lin, адаптировать тяжело, вечерком одним не отделаться :'(
На счёт dll вариант.
Спасибо.

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » HTTP запрос - несколько вопросов