How to sent a request by HTTP using relative url? - http

There's a HTTP Message like:
POST /v1.0/oauth2/accessToken HTTP/1.1
Host:api.dingtalk.com
Content-Type:application/json
{
...
}
If I want to send it by HTTP.post function, I should let url = "https://api.dingtalk.com/v1.0/oauth2/accessToken".
Could I use relative url url = "/v1.0/oauth2/accessToken", and write "host" => "api.dingtalk.com" in headers?
I know this is wrong way, I'm wondering how to separate them in two parts while using HTTP.request()?
I Tried:
url = "/v1.0/oauth2/accessToken"
headers = Dict([(
"host" => "api.dingtalk.com",
"Content-Type" => "application/json"
)])
body = Dict([
...
])
r = HTTP.post(url, headers, body)
get:
ERROR: ArgumentError: missing or unsupported scheme in URL (expected http(s) or ws(s)): v1.0/oauth2/accessToken
obviously it doesn't work.

With HTTP.request(), you can also use a relative URL and a Dict object for the headers as you've attempted, but you need to provide the full URL (including the protocol) as the base_uri argument, like this:
using HTTP
using JSON
base_uri = "https://api.dingtalk.com"
url = "/v1.0/oauth2/accessToken"'
full_url = base_uri * endpoint
headers = Dict([
"host" => "api.dingtalk.com",
"Content-Type" => "application/json"
])
body = Dict([
# your request body here
])
response = HTTP.request("POST", full_url, headers, JSON.json(body))
Hope this helps!

Related

How would one send an HTTP POST request?

I'm using lua-http for HTTP requests in my Lua script. I'm trying to find a way to send data as a POST request, similar to the -d option of curl.
I've tried new_from_uri:set_body() but I don't think I'm doing it correctly.
request = require "http.request"
headers, stream = assert(request.new_from_uri("https://example.org"):set_body("body text"))
headers, stream = assert(request.new_from_uri("https://example.org"):go())
body = assert(stream:get_body_as_string())
if headers:get ":status" ~= "200" then
error(body)
end
Could someone show me how to do this properly?
I've decided to use luasocket for this instead. Here is the code I'm using:
http = require "socket.http"
body = "body text"
respbody = {
result, respcode, respheaders, respstatus = http.request {
method = "POST",
url = "https://example.org",
source = ltn12.source.string(body),
headers = {
["content-type"] = "application/json", -- change if you're not sending JSON
["content-length"] = tostring(#body)
},
sink = ltn12.sink.table(respbody)
}
respbody = table.concat(respbody)

converting python POST request into R httr POST request

I have the following code in python which returns a 200 status:
> credentials = {
> 'grant_type': 'client_credentials',
> 'scope':'various scopes go here'
> }
> response = requests.post('https://sample_website.com/oauth/token',
> headers = {"Authorization": "Basic {}".format(signed_request),
> "Content-Type":"application/x-www-form-urlencoded"},
> data = credentials
> )
when i try the following code using the same signed_request I get a 401 error
credentials <- "{'grant_type': 'client_credentials','scope':'various scopes'}"
response <- POST(url = 'https://sample_website.com/oauth/token',
add_headers(
Authorization = signed_request,
'Content-Type' = 'application/x-www-form-urlencoded'
),
accept('application/json'),
body = credentials,
encode = 'json',
verbose()
)
I can't figure out what I am doing wrong but I'm assuming that I am not formatting the body correct or there might be an issue with the headers I am passing.
Your body is appropriate for the content type "application/json", but not for "x-www-form-urlencoded". The easiest solution is to pass a list, and let R take care of serialising it for you.
body <- list(
grant_type="client_credentials",
scope="scopes"
)
POST(url=*,
add_headers(Authorization=paste("Basic", signed_request)),
body=body,
encode="form"
)
Depending on what it is you're doing, you may also want to try the httr2 package (the successor to httr) and its built-in OAuth authentications options, among which is client credentials.

How to send basic authorization header with Python3.6.9 urllib3

I am trying to send an API call to get the time from the Questrade platform. Here is the sample request from their guide
GET /v1/time HTTP/1.1
Host: https://api01.iq.questrade.com
Authorization: Bearer C3lTUKuNQrAAmSD/TPjuV/HI7aNrAwDp
I am able to get it working with the request module
headers = {'Authorization': f'{token_type} {access_token}'}
print(headers) -> {'Authorization': 'Bearer -xSoUNCLYCrFjxxxxx_wAQVpi4olWrQs0'}
qt_time_obj = requests.get(api_server + 'v1/time', headers=headers)
qt_time = qt_time_obj.json()['time']
print(qt_time) -> 2020-10-13T17:06:32.388000-04:00
Now I am trying to get urllib3 to work but without luck
headers = {'Authorization': f'{token_type} {access_token}'}
url = api_server + 'v1/time'
http = urllib3.PoolManager()
qt_time_obj = http.urlopen('GET', url, headers)
print(qt_time_obj.status) -> 401
print(qt_time_obj.data) -> b'{"code":1014,"message":"Missing authorization header"}'
I also tried with the make_headers method but it gives me the same error.
headers = urllib3.make_headers(basic_auth="Authorization: Bearer AdKt3YUl46_tGnZp7cRgTu4W2vtfBME50")
Could you point where I did wrong? Thank you!
So after some trying, I found that I need to use http.request instead of the http.open. I also need to do "headers=headers" instead of just the "headers" in the method.
qt_time_obj = http.request('GET', url, headers=headers)

How to serve same response from HttpClient in my controller using Symfony?

I have a Controller that must forward the received request (changing some query parameters) to another server, and returns it's response (with same headers, status and body).
I decided to use HttpClient for doing that.
The problem is that HttpClient converts the content (i.e.: deflating gzip requests), and it breaks the output response.
Here is part of the example:
$response = $client->request($request->getMethod(), $extUrl, [
'headers' => $reqHeaders,
'timeout' => 45,
'verify_host' => false,
'verify_peer' => false,
'body' => $request->getContent(),
]);
#response data
$body = $response->getContent(false);
$statusCode = $response->getStatusCode();
$headers = $response->getHeaders(false);
return new Response($body, $statusCode, $headers);
Considering the second server returns a gzipped content, the response is broken, because it would keep the response header (content-type) but the $body will not be exactly the same, because HttpClient do me the favor of deflate the content.
The question is: is there a way to tell HttpClient to do not touch in my response body?
Or: is there a better way to make this "proxy" controller action?
I found that if accept-encoding is defined in the request headers, it's not inflated by CurlResponse class...
#\Symfony\Component\HttpClient\Response\ResponseTrait::$inflate
$this->inflate = !isset($options['normalized_headers']['accept-encoding']);
And
#\Symfony\Component\HttpClient\Response\response
$response->inflate = \extension_loaded('zlib') && $response->inflate && 'gzip' === ($response->headers['content-encoding'][0] ?? null) ? inflate_init(ZLIB_ENCODING_GZIP) : null;
So, I specified some empty encoding for those cases.
if (empty($request->headers->get('accept-encoding'))) {
//adding some accept-encoding will make httpclient response not to deflate the response (gzdecode) automatically
$request->headers->add(['accept-encoding'=> '']);
}
I still don't know if this is the best approach to forward a request and it's response in the controller, but the above solution solved my problem.

Sending headers to post request

I have this python code that does not work as expected.
import requests
import json
API_ENDPOINT = "https://lkokpdvhc4.execute-api.us-east-1.amazonaws.com/mycall"
data = {'mnumber':'9819838466'}
r = requests.post(url = API_ENDPOINT, data = json.dumps(data))
print (r.text)
This will return an error:
{"stackTrace": [["/var/task/index.py", 5, "handler", "return
mydic[code]"]], "errorType": "KeyError", "errorMessage": "''"}
When I test the API using Amazon console's gateway, I get the expected output (i.e. string like "mumbai"). It means this is client side issue. I have confirmed this by using "postman" as well that returns the same error as mentioned above. How do I send correct headers to post request?
You can create a dictionary with the headers such as
headers = {
"Authorization": "Bearer 12345",
"Content-Type": "application/json",
"key" : "value"
}
Then at the point of making the request pass it as a keyword argument to the request method i.e .post() or .get() or .put
This will be
response = requests.post(API_ENDPOINT, data=json.dumps(data), headers=headers)

Resources