What are cURL headers needed for GMail API (message.send)? - gmail-api

I'm trying to get the GMail API working, for sending an Email. I am building the JSON and cURL requests myself (instead of with a 3rd party library - not able to easily use one of those; and shouldn't need to...)
I got far enough that I have a JSON object that fails when I make the cURL request from my solution (error 400 - Recipient required...), but it WORKS went sent via their 'Try this API' widget on the GMail API docs page.
I'm thinking that I have something wrong in my cURL headers (which would be different between my solution's code and their API widget). So what cURL headers are required? I thought I had looked around, but I am not finding the information. Could be missing something obvious. :)
URL: https://gmail.googleapis.com/upload/gmail/v1/users/me/messages/send
cURL headers used (exact syntax is not this, this is just close-representation):
-X POST
-H Authorization: Bearer <accessToken>
-H Content-Type: message/rfc822
-d <JSON>
Example JSON object:
{"payload":
{"body":
{"data":""}
,"headers":[
{"name":"To","value":"email#email.net"}
,{"name":"From","value":"email#address.com"}
,{"name":"Subject","value":"Test message --- TESTING"}
]
,"mimeType":"text/plain"
,"partId":"1"
}
,"raw":"TUlNRS1WZX... < rest of encoded RFC2822 content>"
}```

Related

How to get gzip or brotli encoding on Google App Engine

Does Google App Engine allow compression of the results? For example, I have the following curl request:
$ curl --location --request GET 'https://premiere-stage2.uk.r.appspot.com/' \
> --header 'Accept-Encoding: gzip, deflate, br'
And the response is not compressed. Compare this with something like:
$ curl --location -X GET 'https://google.com' --header 'Accept-Encoding: gzip, deflate, br'
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
Or, is there something manual I need to set up? I would think the last resort would be to do the compression in the application endpoints themselves, or is that how it needs to be done?
Expanding on John Hanley's suggestion in a comment, there are two parts to this.
You have to set the Accept-Encoding header in the request.
Second, the response itself should have the proper content- or mime-type, such as text/html or whatever it needs to be. Often the web server will ignore compression if the mime-type isn't in a certain list.
Third, to ensure that the headers in both the requests and responses are correct you can use the -v flag in curl.
Finally, it seems the content needs to be over a certain size for the web server to bother compressing it. So, for example, if the content-length is 3, it's not going to be compressed, though I'm not sure exactly what this is.
Putting it all together:
$ curl --location --request GET 'https://premiere-stage2.uk.r.appspot.com/html'
--header 'Accept-Encoding: gzip, deflate, br'
-v
References:
curl
GAE (a bit buried, under the Go documentation)
According to documentation
For example, the server may automatically send a gzipped response depending on the value of the Accept-Encoding request header. The application itself does not need to know which content encodings the client can accept.
That gives the impression it should. But the same documentation also says
In addition, the following headers are removed from incoming requests because they relate to the transfer of the HTTP data between the client and server:
Accept-Encoding
I tested against our production site and in FireFox, Web Developer Tool shows Accept-Encoding: gzip, deflate, br as a request header and a response header of content-encoding: gzip
However, when I tested against local/dev of our site, Web Developer Tool shows Accept-Encoding: gzip, deflate, br as a request header but the response header didn't include content-encoding: gzip. In addition, printing the headers in Flask/Python, gave a value of None for Accept-Encoding

Calling Google IAM generateAccessToken API always returns error

I'm facing the issue where I am not able to generate an Access Token for Google IAM Service Account using this method .
I've got my personal OAuth2 access token using:
gcloud auth application-default print-access-token
I've got all the necessary roles (roles/iam.serviceAccountTokenCreator) but when I cURL the API I always get an error response:
{
"error": {
"code": 400,
"message": "Request contains an invalid argument.",
"status": "INVALID_ARGUMENT"
}
}
This is how full curl request looks like:
curl -X POST --header 'Content-Type: application/json' --header 'authorization: Bearer ya29.AASDSADASDASDi9C1yAXXXXXXZzLtDDrCAzblqF_qi5sKvMZcHieBADASDASDTNJiOKrqJBffb4Moh3gTgiTbDgMIF1XDQU5JZ31aACs0aUbI4wgeqV2Q' https://iamcredentials.googleapis.com/v1/projects/<PROJECT_NAME>/serviceAccounts/<SA_NAME>#<PROJECT_NAME>.iam.gserviceaccount.com:generateAccessToken -d '{"scope": ["https://www.googleapis.com/auth/cloud-platform"]}'
Thanks
You have two problems in your API call.
The Service Account Name is a path parameter and must be URL encoded. The # character is not valid. Use %40 in its place (as an example of correct encoding).
The URI specifies a PROJECT_NAME. This is not correct. You need to use a - (hyphen/dash character). Example projects/-/serviceAccounts.
You also need to have the permission iam.serviceAccounts.getAccessToken attached to one of the roles that are assigned to the account that created the request Access Token use in this API request. This will cause a different error if incorrect. Just a tip as you get to the next step.

Using HTTP Request for Google Dialogflow

https://api.dialogflow.com/v1/query?v=20150910&contexts=shop&lang=en&query=apple&sessionId=12345&timezone=America/New_York
Headers:
Authorization: Bearer YOUR_CLIENT_ACCESS_TOKEN
How do i use the above code to make a HTTP Request in Google Dialogflow? How do i add headers as a part of HTTP request
You can use the Postman application for sending POST request,
Select Post request in Postman Application,
Copy and paste URL https://api.dialogflow.com/v1/query?v=20150910&contexts=shop&lang=en&query=apple&sessionId=12345&timezone=America/New_York
In headers section, choose Authorization as key and paste the Bearer YOUR_CLIENT_ACCESS_TOKEN
Then, if you click send you will get the proper response in a body.
An easy start is to use curl from the command line as in the documentation:
curl \
-H "Authorization: Bearer YOUR_CLIENT_ACCESS_TOKEN" \
"https://api.dialogflow.com/v1/query?v=20150910&contexts=shop&lang=en&query=apple&sessionId=12345&timezone=America/New_York"
Just copy the whole thing and paste it into your command line and you will get a json response.
Ref: https://dialogflow.com/docs/reference/agent/query#get_query_sample

Axios POST request is complaining about cross origin, but curl request works fine

let url = 'http://localhost:4001/api/v1/sessions/new';
axios.post(url, data)
.then(function(resp) {
console.log('resp returned is ' + JSON.stringify(resp));
});
I see this error in chrome console"
Failed to load http://localhost:4001/api/v1/sessions/new: Response
to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:4044' is therefore not allowed
access. The response had HTTP status code 405.
If I just try and curl the exact same API call it works fine:
curl -d "email=hello#asdf.com&password=hello123" -X POST http://localhost:4001/api/v1/sessions/new
{"apiResponse":{"success":true,"errors":[]}}
Why does it work with CURL but not with axios?
Anything that isn't running in a browser doesn't care about CORS. If you'd like your web app to make requests to your server add the Access-Control-Allow-Origin header to your server's response with the most permissive value being *:
Access-Control-Allow-Origin: *

GCP HTTP Load Balancer returns 502 error if POST data is large

We have an API server and are using HTTP Load Balancer. We found that the L7 Load balancer returns 502 error if HTTP request's data is large.
We have confirmed that it works when accessing the API without the Load Balancer (accessing the API Server directly.)
This question might be a similar issue. HTTP Load Balancer cuts out part of a large request body
Someone said that using L4 Network Load Balancer is a possible solution but we don't want to use it for some reasons e.g. URL based load balancing and cross-region load balancing.
// Response OK (data size is 1024)
curl -H "Content-Type: application/json" -X POST -d '{"xx": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}' https://xxxxxxxxxxxxxxx.com/xx/xxxxxxxxxxxx/xxxxxxxxx
// Response NG (data size is 1025)
curl -H "Content-Type: application/json" -X POST -d '{"xx": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}' https://xxxxxxxxxxxxxxx.com/xx/xxxxxxxxxxxx/xxxxxxxxx
It seems that LB has some limitation about the size of post data. Tests show the limit is around 1024 bytes.
Update1
#chaintng saved me. Someone on the linked post says that curl adds "Expect: 100-continue Header" if the post data is over 1024 byte.
// Response NG (data size is 1025. without "Expect: ")
curl -H "Content-Type: application/json" -X POST -d '{"xx": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}' https://xxxxxxxxxxxxxxx.com/xx/xxxxxxxxxxxx/xxxxxxxxx
// Response OK (data size is 1025. with "Expect: ")
curl -H "Expect: " -H "Content-Type: application/json" -X POST -d '{"xx": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}' https://xxxxxxxxxxxxxxx.com/xx/xxxxxxxxxxxx/xxxxxxxxx
reference from this question Curl to Google Compute load balancer gets error 502
It's because CURL has default value when request large POST body defining header as Expect: 100-continue
Which is not support in Google L7 Load Balancing (stated in this document https://cloud.google.com/compute/docs/load-balancing/http/)
All you have to do is ignoring this behaviour by set the header before execute curl.
For e.g. in PHP
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Expect:']);

Resources