Po jakimś czasie zacząłem się interesować modułem GATE HTTP od Grentona. W ramach posta zrobiłem kilka prostych testów, które pozwoliły mi zrozumieć jak działa moduł HTTP GATE. Może komuś się przyda.
Moduł pozwala dodać dwa typy obiektów.
Request – służący do wysyłania zapytań HTTP
oraz
Response – służący jako prosty server HTTP.
W tym wpisie zajmę się obiektem Request, ponieważ za to on pozwala na proste integracje, np. z pogodą.
Postawiłem sobie prosty serwer HTTP napisany w Pythonie i zacząłem wysyłać do niego zapytania za pomocą modułu GATE HTTP. Serwer stoi pod adresem 192.168.0.51 na porcie 8080.
Poniżej lista moich przypadków testowych wraz z wynikiem i krótkim podsumowaniem.
Przypadek 1 (request type none)
local host = “http://192.168.0.51:8080”
local path = “/”
local query = “test=test1”
local method = “GET”
local requestType = 0 — none
local responseType = 0GATE->RequestTest->Clear()
GATE->RequestTest->SetHost(host)
GATE->RequestTest->SetPath(path)
GATE->RequestTest->SetQueryStringParams(query)
GATE->RequestTest->SetMethod(method)
GATE->RequestTest->SetRequestType(requestType)
GATE->RequestTest->SetResponseType(responseType)
GATE->RequestTest->SendRequest()
Wynik:
192.168.0.6 – – [23/Mar/2020 00:33:22] “GET /?test=test1 HTTP/1.0” 200 –
Podsumowanie:
Sewer otrzymał request z GATE HTTP (adres 192.168.0.6) bez nagłówków. Metoda GET oraz z queryString jak w parametrach.
Przypadek 2 (request type text)
local host = “http://192.168.0.51:8080”
local path = “/”
local query = “test=test1”
local method = “GET”
local requestType = 1 — text
local responseType = 0
GATE->RequestTest->Clear()
GATE->RequestTest->SetHost(host)
GATE->RequestTest->SetPath(path)
GATE->RequestTest->SetQueryStringParams(query)
GATE->RequestTest->SetMethod(method)
GATE->RequestTest->SetRequestType(requestType)
GATE->RequestTest->SetResponseType(responseType)
GATE->RequestTest->SendRequest()
Wynik:
Content-Type: text/plain
Content-Length: 0
192.168.0.6 – – [23/Mar/2020 00:35:50] “GET /?test=test1 HTTP/1.0” 200 –
Podsumowanie:
Zmiana typu requestu na type == “text” powoduje dodanie nagłówka Content-Type: text/plain
Przypadek 3 (request type json)
local host = “http://192.168.0.51:8080”
local path = “/”
local query = “test=test1”
local method = “GET”
local requestType = 2 — json
local responseType = 0
GATE->RequestTest->Clear()
GATE->RequestTest->SetHost(host)
GATE->RequestTest->SetPath(path)
GATE->RequestTest->SetQueryStringParams(query)
GATE->RequestTest->SetMethod(method)
GATE->RequestTest->SetRequestType(requestType)
GATE->RequestTest->SetResponseType(responseType)
GATE->RequestTest->SendRequest()
Wynik:
Content-Type: application/json
Content-Length: 0
192.168.0.6 – – [23/Mar/2020 00:37:53] “GET /?test=test1 HTTP/1.0” 200 –
Podsumowanie:
Bez niespodzianek. Zmienił się ponownie nagłówek.
Przypadek 4 (request type xml)
Tu request taki sam jak wyżej, jedynie requestType zmieniony na xml(3).
Wynik:
Content-Type: text/xml
Content-Length: 0
192.168.0.6 – – [23/Mar/2020 00:39:03] “GET /?test=test1 HTTP/1.0” 200 –
Podsumowanie:
Bez niespodzianek. Zmienił się ponownie nagłówek.
Przypadek 5 (request form data)
Tu request taki sam jak wyżej, jedynie requestType zmieniony na form-data(4).
Wynik:
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
192.168.0.6 – – [23/Mar/2020 00:40:32] “GET /?test=test1 HTTP/1.0” 200 –
Podsumowanie:
Bez niespodzianek – nagłówek.
Przypadek 5 (request other)
Tu request taki sam jak wyżej, jedynie requestType zmieniony na other(5).
Wynik:
`192.168.0.6 – – [23/Mar/2020 00:41:58] “GET /?test=test1 HTTP/1.0” 200 –
Podsumowanie:
Wynik taki sam jak przy None. Nie rozumiem jaka jest różnica. Brak nagłówka.
Przypadek 6 (ustawienie własnych nagłówków)
local host = “http://192.168.0.51:8080”
local path = “/”
local query = “test=test1”
local method = “GET”
local requestType = 2 — json
local responseType = 0
local headers = {} — tablica z nagłówkami
headers[“Access-Token”] = “baerer 1234” — pierwszy nagówek
headers[“test1”] = “test2” — drugi nagówek
GATE->RequestTest->Clear()
GATE->RequestTest->SetHost(host)
GATE->RequestTest->SetPath(path)
GATE->RequestTest->SetQueryStringParams(query)
GATE->RequestTest->SetMethod(method)
GATE->RequestTest->SetRequestHeaders(headers)
GATE->RequestTest->SetRequestType(requestType)
GATE->RequestTest->SetResponseType(responseType)
GATE->RequestTest->SendRequest()
Wynik:
192.168.0.6 – – [23/Mar/2020 00:52:27] “GET /?test=test1 HTTP/1.0” 200 –
Access-Token: baerer 1234
test1: test2
Content-Type: application/json
Content-Length: 0
Podsumowanie:
Wybranie RequestType powoduje, że nagłówek application/json zostanie dodany po nagłówkach, które sami zdefiniujemy. Czyli nagłówki nie są nadpisywane.
Przypadek 6 (post text)
Ciekawszy przypadek – metoda post
local host = “http://192.168.0.51:8080”
local path = “/”
local query = “test=test1”
local method = “POST”
local requestType = 1 — text
local responseType = 0
local headers = {}
headers[“Access-Token”] = “baerer 1234”
headers[“test1”] = “test2”
local body = “text, text, text” — tu wysyłamy treśćGATE->RequestTest->Clear()
GATE->RequestTest->SetHost(host)
GATE->RequestTest->SetPath(path)
GATE->RequestTest->SetQueryStringParams(query)
GATE->RequestTest->SetMethod(method)
GATE->RequestTest->SetRequestHeaders(headers)
GATE->RequestTest->SetRequestBody(body)
GATE->RequestTest->SetRequestType(requestType)
GATE->RequestTest->SetResponseType(responseType)
GATE->RequestTest->SendRequest()
Wynik:
Path: /?test=test1
Headers:
Host: 192.168.0.51
Access-Token: baerer 1234
test1: test2
Content-Type: text/plain
Content-Length: 16Body:
text, text, text
Podsumowanie:
Wygląda, że działa tak jak trzeba.
Przypadek 6 (post json, xml, data-form)
local host = “http://192.168.0.51:8080”
local path = “/”
local query = “test=test1”
local method = “POST”
local requestType = 2 — json
local responseType = 0
local headers = {}
headers[“Access-Token”] = “baerer 1234”
headers[“test1”] = “test2”local body = {} — próba wysłania tablicy, liczę na to, że Gate przerobi to na JSON.
body[“test”] = “hello world”GATE->RequestTest->Clear()
GATE->RequestTest->SetHost(host)
GATE->RequestTest->SetPath(path)
GATE->RequestTest->SetQueryStringParams(query)
GATE->RequestTest->SetMethod(method)
GATE->RequestTest->SetRequestHeaders(headers)
GATE->RequestTest->SetRequestBody(body)
GATE->RequestTest->SetRequestType(requestType)
GATE->RequestTest->SetResponseType(responseType)
GATE->RequestTest->SendRequest()
Wynik:
brak
Podsumowanie:
W tym wypadku GATE zachowuje się inaczej niż się spodziewałem. Nie potrafi zmienić tablicy LUA na JSON, XML czy data-form. W przypadku response, dane zwrotne w miarę możliwości parsowane są na tablice. Wysyłanie query string jako tablica też nie działa.
Przypadek 7 (response json)
Wysłanie requestu GET do API od pogody.
local town = “Warsaw,pl”
local appid = “123456789” — tutaj twój appid
local units = “metric”
local query = “q=” .. town .. “&appid=” .. appid .. “&units=” .. units
GATE->Request1->Clear()
GATE->Request1->SetHost(“http://api.openweathermap.org”)
GATE->Request1->SetPath(“/data/2.5/weather”)
GATE->Request1->SetQueryStringParams(query)
GATE->Request1->SetMethod(“GET”)
GATE->Request1->SetRequestType(2)
GATE->Request1->SetResponseType(2)
GATE->Request1->SendRequest()
Po wysłaniu requestu, zostanie wywołany event onResponse, oznacza to, że zostało wypełnione pole ResponseBody oraz StatusCode. Dla typu JSON w ResponseBody znajdzie się tablica LUA. Json wygląda następująco.
{
“coord”: {
“lon”: 21.01,
“lat”: 52.23
},
“weather”: [
{
“id”: 803,
“main”: “Clouds”,
“description”: “broken clouds”,
“icon”: “04n”
}
],
“base”: “stations”,
“main”: {
“temp”: 2.28,
“feels_like”: -5.77,
“temp_min”: 0,
“temp_max”: 4.44,
“pressure”: 1033,
“humidity”: 27
},
“visibility”: 10000,
“wind”: {
“speed”: 6.7,
“deg”: 20
},
“clouds”: {
“all”: 59
},
“dt”: 1584896271,
“sys”: {
“type”: 1,
“id”: 1713,
“country”: “PL”,
“sunrise”: 1584851592,
“sunset”: 1584895932
},
“timezone”: 3600,
“id”: 756135,
“name”: “Warsaw”,
“cod”: 200
}
I teraz po stronie LUA, żeby się dostać do pól można napisać taki kod:
local body = GATE->Request1->ResponseBody
local temp = body.main.temp — temperatura
local pressure = body.main.pressure — cisnienie
local icon = body.weather[1].icon — ikonka
Podsumowanie
Wydaje mi się, że przedstawiłem większość najciekawszych przypadków jak zachowuje się obiekt Request. Trochę się zawiodłem nad typami requestu, bo wygląda na to, że one jedynie dodają nagłówek, więc ostatecznie cały request i tak można stworzyć samemu, używając jedynie typu none i inne typy nie są potrzebne. Można użyć bibliotek zewnętrznych, żeby zamieniać tablice LUA na json lub xml. Może to temat na kolejny post.
Dla JSON: https://github.com/rxi/json.lua/blob/master/json.lua
Dla XML: https://github.com/manoelcampos/xml2lua
Ale w przypadku XML wymaga to odrobinę zachodu, żeby wrzucić cały skrypt do jednego pliku.
Instrukcję od Grentona można znaleźć pod adresem: https://www.grenton.pl/upload/files/PL/GATE-HTTP_User-Manual-Draft_pl_v0.3.pdf
Pozdrawiam,
T