Pass data for GET request using Hyper - rust

I am working on a Twitter API for Rust and am running into issues with passing arguments to my GET request. The code I'm using for the request is given below. data_body is something like "screen_name=a_user" and the authorization header is the OAuth authorization required by Twitter (this isn't the issue as it's working with all my other requests).
let mut res = client.get("http://httpbin.org/get")
.body(&data_body[..])
.header(Authorization(authorization_header))
.header(ContentType::form_url_encoded())
.send().unwrap();
I started sending this to httpbin.org so I could see the raw request. What I'm getting back is shown below.
{
"args": {},
"headers": {
"Authorization": "OAuth oauth_consumer_key=\"\", oauth_nonce=\"RH9vZYMCbAtfQAuVh44fhlyGQfQqBCPq\", oauth_signature=\"dTbOyaURct0auVlC%2B8Y7vDFpus0%3D\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1452648640\", oauth_token=\"\", oauth_version=\"1.0\"",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org"
},
"origin": "0.0.0.0",
"url": "http://httpbin.org/get"
}
The curl request given by the Twitter api docs have a data portion for the GET request below (I've replaced my keys with empty strings). I can confirm this works for the GET.
curl --get 'https://api.twitter.com/1.1/users/show.json' --data 'screen_name=twitterdev' --header 'Authorization: OAuth oauth_consumer_key="", oauth_nonce="6a37886cb38b2f5e12dee8fd47aa097c", oauth_signature="zhXDA5JbKRmw2xbJcEqK9sxuu5E%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1452647580", oauth_token="", oauth_version="1.0"' --verbose
I've tried a bunch of different ContentTypes from the Hyper API but can't get the args section of the HTTP request populated. I think that's the issue, but I don't have a lot of experience with HTTP so I could very well be wrong. Ultimately the request is returning a 403 (Unauthorized) which is triggered by the missing args. I know my OAuth header is being generated correctly because it's working on all the POST requests and when I copy over the nonce and timestamp from the curl command I get from the Twitter API the signature matches.

As #hamersaw said, "GET parameters" are part of URL, in the query string. If you need to set parameters programatically (if they’re not always the same), the Url::set_query_from_pairs method can take care of the escaping/encoding for you:
use hyper::Url;
let mut url = Url::parse("https://api.twitter.com/1.1/users/show.json").unwrap();
url.set_query_from_pairs([
("screen_name", "twitterdev"),
].iter().cloned());
let res = client.get(url) // ...

Figured it out. Turns out in a GET request you have to append the body to the request and it will automatically fill out in the packet. Below is the code to get it working.
let mut res = client.get("http://httpbin.org/get?screen_name=twitter")
.header(Authorization(authorization_header))
.send().unwrap();

Related

What is the "troute=t1" cookie setting in curl? and how can it be emulated in NodeJS

When trying to figure out why I was getting an error 403 while making a get request, I came across this post, that offered a solution by adding the header:
'Cookie': 'troute=t1'
to the request. I also found another post that mentions the same solution, but doesnt provide any guidance as to what it actually means, or how to utilize this setting? in other request libraries.
Does anyone have any idea what this cookie means? and how I could use the same sort of setting in a nodejs library such as got, fetch etc.
** For context, the specific request Im trying to make is to download a csv from the nasdaq website:
curl -L -H 'User-Agent: Mozilla' -H 'Cookie: troute=t1;' 'https://old.nasdaq.com/screening/companies-by-name.aspx?letter=0&exchange=&render=download'
Using a similar request in got/fetch just responds with an error message saying the cookie property is not settable in fetch, and Response code 403 from got.
ie:
const got = require("got");
const url = "https://old.nasdaq.com/screening/companies-by-name.aspx?letter=0&exchange=&render=download";
got(url { http2: true, headers: {'user-agent': 'Mozilla', cookie:'troute=t1' }}).text();

How to upload video from the API imgur

I'm using imgur API and I have several question, what is the size limit for uploading a .gif ? I read everywhere the size limit of picture is 10Mb and gif are 20Mb but when I try to upload a gif of 11Mb with the API it tells me it's too heavy.
Also Im trying to upload a video (.mp4 , 6,9Mb) and I use the following request with postman
https://api.imgur.com/3/image?client_id={myclientid}
and in the body
video={mavideo.mp4}
but it return me a success with no information
{
"data": {
"errorCode": null,
"ticket": "90c70cdc"
},
"success": true,
"status": 200
}
I have followed the api documentation to make this request
Thank you.
EDIT:
Ok it work if I'm using
https://api.imgur.com/3/upload in postman but when I try to use it with ajax like this
if (fileExtension == "mp4" || fileExtension == "webm"){
form.append('video', file);
} else {
form.append('img', file);
}
$.ajax({
url: 'https://api.imgur.com/3/upload',
headers: {
Authorization: "Client-ID " + ClientId },
type: 'POST',
data: form,
cache: false,
contentType: false,
processData: false
})
I have got the message Access to XMLHttpRequest at 'https://api.imgur.com/3/upload' from origin 'http://localhost:3010' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What is wrong ?
Not really an answer, but we both seem to be trying to get this working at the same time, so i will share what i found out.
As you seem to have found out also, there are 2 endpoints for uploading, /image and /upload.
When uploading video, /image returns a ticket id. This is probably meant to get the state of the queued processing. There is however no endpoint available where you can send the ticket id and get the state back.
Second endpont, /upload has however another bunch of issues.
While it does return a more useable object with image id and url, it seems to completely ignore the authorization header. Any image that i managed to upload this way has null for the uploaded user, and i don't see it in my account. (using oauth2 and sending Authorization: Bearer <token>) Even if i omit the header completely, it still works even though Authorization is mandatory for uploading.
Another weird thing is, if i don't send the auth header BUT add anything to the query params (so ?some=thing or whatever) it suddenly wakes up and starts requiring the authorization header. When i send it again at this point however, we are back at the beginning and even the /upload endpoint starts sending ticket id and not a reasonable response.
This is a CORS issue and needs to be fixed by the imgur devs. It's only an issue when doing client-side JavaScript as curl works just fine:
echo 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' | base64 --decode | curl --location --request POST 'https://api.imgur.com/3/upload' --header "Authorization: Client-ID $CLIENT_ID" -F 'type=file' -F 'disable_audio=0' -F 'image=#-'

Not getting data of GITHUB api using npm module sync-request

I am trying to get data of below url using sync-request module.
https://api.github.com/repos/rethinkdb/rethinkdb/stargazers
I get the data when i call it in browser or through postman.
But i am getting 403 forbidden error when calling it using sync-request in my node api.
My code looks like this.
var request = require("sync-request");
var response = request('GET', 'https://api.github.com/repos/rethinkdb/rethinkdb/stargazers', {
headers: {},
json: true
});
I am able to fetch data of many other api's but not this one. Please help.
Response body already contains the explanation:
Request forbidden by administrative rules. Please make sure your request has a User-Agent header (http://developer.github.com/v3/#user-agent-required). Check https://developer.github.com for other possible causes.
It will work like:
var response = request('GET', 'https://api.github.com/repos/rethinkdb/rethinkdb/stargazers', {
headers: { 'User-Agent': 'Request' },
json: true
});
The use of sync-request is strongly discouraged because synchronousness is achieved via a hack and may block the process for a long time.
For sequential execution request-promise can be used together with async..await.
Try to use an access token along with the GitHub API call
like this
[https://api.github.com/repos/rethinkdb/rethinkdb/stargazers?access_token=f33d1f112b7883456c990028539a22143243aea9]
As you say the API works in the browser it should not be an issue.
When you use too many calls through the GitHub API they they give the following message
{
"message": "API rate limit exceeded for 192.248.24.50. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
"documentation_url": "https://developer.github.com/v3/#rate-limiting"
}
To overcome this issue you can use an access token using an access token you can to access the private repositories in your account as well .
Here is the link for to get an access token [https://github.com/settings/developers]

shopify - nodejs - get permanent token fails

I have written an application that talks with the shopify API. I manage to get the temporary code from shopify and redirect back to my app where I store the code to later exchange for the permanent token.
According to the docs all I need to do is then send a POST request to https://{shop}.myshopify.com/admin/oauth/access_token with the client_id, client_secret and code is the body of the request.
I am using the request module to send the request and have it set up to send the request as such:
var options = {
method: POST,
url: https://my-develop-shop.myshopify.com/admin/oauth/access_token,
json: true
};
var _body = {
"client_id": config.get('SHOP_ID'),
"client_secret": config.get('SHOP_SECRET'),
"code": tempCode
}
_body = JSON.stringify(_body);
options.body = _body;
request(options, callback);
However when I send the request it always returns with : error_description: 'Could not find Shopify API application with api_key ' }
The app is installed successfully on the client's shop, so why would this error be returned?
Is there a special header that shopify expects? The docs are so vague.
Why does it not authenticate?
Well I cheated and used the shopify-node-api package. There I just use the exchange_temporary_token method. This api also handles throttling so it's a decent investment in the time you might spend incorporating it.

Angular2 http GET with Body?

I'm querying some elasticsearch servers from my Angular2 site. To help with security, we'd like to lock down access to only GET requests. Elasticsearch supports GET with a body but I'm having troubles making it happen with Angular2's http class.
this.http.post(SearchEndpoint, q.BuildPayload(), { method: 'GET' })
Since http.get doesn't have a body parameter, I am trying to use the post method. Previously I would leave off the RequestOptionsArgs of { method: 'GET' } and the POST would go through successfully with the body. By specifying the method in the third parameter the http class removes the body from the request.
Is it possible to make a GET request with a body in Angular 2?
I think that the raw XHR object doesn't allow this. To quote the specification (see https://xhr.spec.whatwg.org/):
4.5.6 The send() method
client . send([body = null])
Initiates the request. The optional argument provides the request body.
The argument is ignored if request method is GET or HEAD.
The send(body) method must run these steps:
If state is not opened, throw an InvalidStateError exception.
If the send() flag is set, throw an InvalidStateError exception.
If the request method is GET or HEAD, set body to null.
This discussion in the Postman github could also help you: https://github.com/postmanlabs/postman-app-support/issues/131.
If you want to query an ElasticSearch server, you can use POST requests. Here is a sample:
POST http://localhost:9200/myindex/mytype/_search?pretty=true
Content-Type: application/json
{
"query": {
"match": {
"somefield": "some value"
}
}
}
Hope it helps you,
Thierry
FWIW, I would be interested in hearing why this is desirable in https://github.com/whatwg/fetch/issues/83. For now there's no browser-based API that supports this, but we could offer it as a feature in fetch() given a convincing enough argument (and implementer interest).

Resources