1

Тема: AHK: WinHttpRequest, gzip, deflate

Всем добра!

При POST запросе, приходит ответом длиннющий JSON, содержимое которого не извлечь из-за того, что он сжат(gzip).
Пытался приспособить для нужд вариант отсюда, но как выяснилось, он сам по себе не рабочий.

Поиск не привёл к решению. Помогите пожалуйста побороть невзгоду.
Win 7 x64, AHK 1.1.30.01 x64

2

Re: AHK: WinHttpRequest, gzip, deflate

http://forum.script-coding.com/viewtopic.php?id=12618

3

Re: AHK: WinHttpRequest, gzip, deflate


Get() {
	oHTTP := ComObjCreate("WinHttp.WinHttpRequest.5.1")
    oHTTP.Open("GET", "http://ahkscript.org/boards/", True)
    oHTTP.SetRequestHeader("Accept-Encoding", "gzip, deflate")
    oHTTP.Send()
    oHTTP.WaitForResponse()
    Return oHTTP.ResponseBody
}

Возвращает массив байт.


result := Get()
r := zlib_Decompress(decompress, result, result.MaxIndex())
MsgBox % StrGet(&decompress, "UTF-8") "`n" result.MaxIndex() "`n" r

В результате пустая строка. Подскажите пожалуйста, в чём ошибка?

4 (изменено: Malcev, 2019-02-12 07:14:57)

Re: AHK: WinHttpRequest, gzip, deflate

По-дефалту ZLib разархивирует формат zlib.
Чтобы он разархивировал gzip, как я понял, нужно будет указать в InflateInit2 - 31, после чего в цикле распаковывать через inflate().
https://www.zlib.net/zlib_how.html
Кстати, у меня код от lexikos на 32 бит ахк работает.
Ну и с массивом байт, думаю, не будет работать - нужен пойнтер + длина равна не result.MaxIndex(), а result.MaxIndex()+1.

5 (изменено: teadrinker, 2019-02-12 12:29:10)

Re: AHK: WinHttpRequest, gzip, deflate

Malcev пишет:

Современная dll для 64 бит систем: https://sourceforge.net/projects/libpng … ;download=

У меня по этой ссылке 32-битная скачивается.
Вот так с помощью js-библиотеки paco.js получилось:

SetBatchLines, -1

oHTTP := ComObjCreate("WinHttp.WinHttpRequest.5.1")
oHTTP.Open("GET", "http://ahkscript.org/boards/", false)
oHTTP.SetRequestHeader("Accept-Encoding", "gzip, deflate")
oHTTP.Send()
arr := oHTTP.ResponseBody
length := arr.MaxIndex() + 1
pData := NumGet( ComObjValue(arr) + 8 + A_PtrSize )

start := A_TickCount
res := GzipDecode(pData, length)

MsgBox, % "Завершено за " . A_TickCount - start . " мс`n`n" . res

GzipDecode(pData, size) {
   arr := "["
   Loop % size
      arr .= (arr = "[" ? "" : ",") . NumGet(pData + A_Index - 1, "UChar")
   arr .= "]"

   html =
   (
   <!DOCTYPE html>
   <html>
   <head>
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <script src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.8/pako.min.js"></script>
     <script>
       var charData = %arr%;
       var binData  = new Uint8Array(charData);
       var data     = pako.inflate(binData);
       var strData  = String.fromCharCode.apply(null, new Uint16Array(data));
     </script>
   </head>
   </html>
   )
   oDoc := ComObjCreate("htmlfile")
   oDoc.write(html)
   Loop {
      Sleep, 10
      try res := oDoc.parentWindow.strData
      catch
        continue
      break
   }
   Return res
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6

Re: AHK: WinHttpRequest, gzip, deflate

Действительно 32 бита.
Тогда надо на просторах инета искать.
Вариант через js годится, если скорость не так сильно важна, так как будет медленнее чем через dll.
Кстати, у меня какая-то комовская ошибка выскакивает.
StrData - 0x80020006 - Unknown name.
Можно еще попробовать перенести вариант с автоит - там разработчик вообще машинным кодом библиотеку прописал:
https://www.autoitscript.com/forum/topi … nt-1312432

7

Re: AHK: WinHttpRequest, gzip, deflate

Вот здесь 64-битная.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8

Re: AHK: WinHttpRequest, gzip, deflate

Malcev пишет:

Кстати, у меня какая-то комовская ошибка выскакивает.

Подправил.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9

Re: AHK: WinHttpRequest, gzip, deflate

Нижайше кланяюсь!

10

Re: AHK: WinHttpRequest, gzip, deflate

Пробовал с dll — что-то не вышло пока, на первой же функции возвращает Z_VERSION_ERROR (-6).

SetBatchLines, -1
zlibPath := "C:\Program Files\Git\mingw64\libexec\git-core\zlib1.dll"

oHTTP := ComObjCreate("WinHttp.WinHttpRequest.5.1")
oHTTP.Open("GET", "http://ahkscript.org/boards/", false)
oHTTP.SetRequestHeader("Accept-Encoding", "gzip, deflate")
oHTTP.Send()
arr := oHTTP.ResponseBody
length := arr.MaxIndex() + 1
pData := NumGet( ComObjValue(arr) + 8 + A_PtrSize )


gzip_inflate(zlibPath, pData, length, uncompr, length*10)
MsgBox, % uncompr

gzip_inflate(zlibPath, pData, inLength, uncompr, outLength) {
   if !DllCall("LoadLibrary", Str, zlibPath)
      throw Exception("Can't load zlib1.dll. A_LastError: " . A_LastError)
   VarSetCapacity(uncompr, outLength, 0)
   VarSetCapacity(z_stream_s, A_PtrSize*4 + 4*10, 0)
   NumPut(pData, z_stream_s)
   NumPut(inLength, z_stream_s, A_PtrSize, "UInt")
   NumPut(&uncompr, z_stream_s, A_PtrSize + 8)
   NumPut(outLength, z_stream_s, A_PtrSize + 8 + A_PtrSize, "UInt")
   MsgBox, % DllCall(zlibPath . "\inflateInit2_", Ptr, &z_stream_s, Int, 16 + (MAX_WBITS := 15))
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11 (изменено: Malcev, 2019-02-12 18:57:03)

Re: AHK: WinHttpRequest, gzip, deflate

Так надо:

VarSetCapacity(stream, 24 + 8*A_PtrSize, 0)
MsgBox, % DllCall("zlib1.dll\inflateInit2_", Ptr, &stream, Int, 16 + (MAX_WBITS := 15), "astr", 1, int, 24 + 8*A_PtrSize, "cdecl")

12 (изменено: teadrinker, 2019-02-12 21:30:11)

Re: AHK: WinHttpRequest, gzip, deflate

Вот так вышло:

SetBatchLines, -1
zlibPath := "D:\Downloads\zlib\bin\zlib1.dll"

oHTTP := ComObjCreate("WinHttp.WinHttpRequest.5.1")
oHTTP.Open("GET", "http://ahkscript.org/boards/", false)
oHTTP.SetRequestHeader("Accept-Encoding", "gzip, deflate")
oHTTP.Send()
arr := oHTTP.ResponseBody
length := arr.MaxIndex() + 1
pData := NumGet( ComObjValue(arr) + 8 + A_PtrSize )

start := A_TickCount
size := gzip_inflate(zlibPath, pData, length, uncompr)
res := StrGet(&uncompr, size, "utf-8")

MsgBox, % "Завершено за " . A_TickCount - start . " мс`n`n" . res

gzip_inflate(zlib, pComprData, comprLen, ByRef uncompr) {
   static MAX_WBITS := 15, Z_OK := 0, Z_FINISH := 4, Z_STREAM_END := 1
        , errors := ["Z_ERRNO", "Z_STREAM_ERROR", "Z_DATA_ERROR", "Z_MEM_ERROR", "Z_BUF_ERROR", "Z_VERSION_ERROR"]
        
   if !hLib := DllCall("LoadLibrary", Str, zlib, Ptr)
      throw Exception("Can't load zlib1.dll. A_LastError: " . A_LastError)
   
   VarSetCapacity(uncompr, outMaxLen := comprLen*10, 0)
   VarSetCapacity(stream, szStream := 24 + 8*A_PtrSize, 0)
   NumPut(pComprData, stream)
   NumPut(comprLen, stream, A_PtrSize, "UInt")
   NumPut(&uncompr, stream, A_PtrSize + 8)
   NumPut(outMaxLen, stream, A_PtrSize + 8 + A_PtrSize, "UInt")
   Loop 1 {
      res := DllCall(zlib . "\inflateInit2_", Ptr, &stream, Int, 16 + MAX_WBITS, AStr, "1", Int, szStream)
      if ( res != Z_OK && error := "inflateInit2_: " . errors[-res] )
         break
      
      res := DllCall(zlib . "\inflate", Ptr, &stream, Int, Z_FINISH)
      if ( res != Z_STREAM_END && error := "inflate: " . errors[-res] )
         break
      
      res := DllCall(zlib . "\inflateEnd", Ptr, &stream)
      ( res != Z_OK && error := "inflateEnd: " . errors[-res] )
   }
   DllCall("FreeLibrary", Ptr, hLib)
   if error
      throw Exception(error)
   Return outLen := NumGet(stream, A_PtrSize + 8 + A_PtrSize + 4, "UInt")
}

Не знаю, всё ли правильно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AHK: WinHttpRequest, gzip, deflate

Ноль времени - это идеально.
Работает без нареканий.
Большое спасибо!