Gmail REST api batch support for getting messages - gmail

We need to switch from google client library to Gmail REST api in our project, and I've encountered a problem with batch() because it is not available in REST api - you can only get list of ids of messages and then get each message one by one using it's id.
If we use that gmail library everything seems to be clear. We create a batch object and then queue each GET request inside of it. We don't have to care how it's implemented inside.
At the moment I'm trying to do some POC and I'm testing these suggestions https://developers.google.com/gmail/api/guides/batch
with Postman but with no luck..
I'm getting 400 bad request.
How should a proper request body look like in Postman (or other application)?
The next step will be implementing multipart request in Java and sending POST using RestTemplate but I need to present some POC in Postman first.
I'm setting it like on this screenshot ->
Postman
What am I doing wrong?:)

You are close. Here is a working example:
Request
POST https://www.googleapis.com/batch
Content-Type: multipart/mixed; boundary="foo_bar"
Authorization: Bearer {ACCESS_TOKEN}
--foo_bar
Content-Type: application/http
GET /gmail/v1/users/me/messages/152d10540c21bd07
--foo_bar
Content-Type: application/http
GET /gmail/v1/users/me/messages/152d1050d666d7ad
--foo_bar--
Response
--batch_7Xp52oGIwpA_AAEAc7ERnGU
Content-Type: application/http
HTTP/1.1 200 OK
ETag: "A-DdBGA6g-wV4rIZCu5Hcm3JQpY/w2hzEg9kqXFH7AEJ-oSc-y10HNQ"
Content-Type: application/json; charset=UTF-8
Date: Thu, 11 Feb 2016 16:02:06 GMT
Expires: Thu, 11 Feb 2016 16:02:06 GMT
Cache-Control: private, max-age=0
Content-Length: 2809
{
"id": "152d10540c21bd07",
"threadId": "152d1050d666d7ad",
"labelIds": [
"SENT",
"INBOX",
"IMPORTANT"
],
"snippet": "Likewise buddy.", ...
}
--batch_7Xp52oGIwpA_AAEAc7ERnGU
Content-Type: application/http
HTTP/1.1 200 OK
ETag: "A-DdBGA6g-wV4rIZCu5Hcm3JQpY/7v2nqQFBDmEHVvEQoboiwSidilE"
Content-Type: application/json; charset=UTF-8
Date: Thu, 11 Feb 2016 16:02:06 GMT
Expires: Thu, 11 Feb 2016 16:02:06 GMT
Cache-Control: private, max-age=0
Content-Length: 1752
{
"id": "152d1050d666d7ad",
"threadId": "152d1050d666d7ad",
"labelIds": [
"SENT",
"INBOX",
"IMPORTANT"
],
"snippet": "Nice to meet you.", ...
}
--batch_7Xp52oGIwpA_AAEAc7ERnGU--
You don't have to specify the host in each part of the batch, and giving the access token in the Authorization header is enough. You don't have to specify the Content-Length yourself, and don't forget to wrap you boundary string with ".
Then you just have to parse the JSON of each part and you are done.

You need to include gmail/v1 on the POST URL and on each request.
Don't forget about the " around your boundary on the Content-Type header.
See original batch gmail requests documentation: https://developers.google.com/gmail/api/guides/batch
The following worked for me:
POST /batch/gmail/v1 HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {YOUR_ACCESS_TOKEN}
Content-Type: multipart/mixed; boundary="foo_bar"
--foo_bar
Content-Type: application/http
GET /gmail/v1/users/me/messages/1732ebdcb9b8cccf
--foo_bar
Content-Type: application/http
GET /gmail/v1/users/me/messages/1732ecadae4907e2
--foo_bar--
Creating request with Postman - body screenshot
Creating request with Postman - headers screenshot

Just wanted to say that Lucila's answer is now the correct one - the global (https://www.googleapis.com/batch) endpoint is now deprecated, and you must make a post request to your request-specific endpoint (https://www.googleapis.com/batch/gmail/v1 for gmail, for instance).
See this link for additional context.
Apologies for making a new answer for this, I don't have enough reputation to leave a comment.

Related

SharePoint REST API Online batch request issues : getting 400 Bad Request, odata.error Invalid request

I'm having a bit of trouble isolating a batch request using the _api/$batch request. I'm sure there is just some simple mistake/issue going on, but I can't just pinpoint this. Any ideas?
Here are some snippets of the raw postman console logs for the request:
POST /_api/$batch HTTP/1.1
Accept: application/json; odata=nometadata
Content-Type: multipart/mixed; boundary="batch_8215457c-c4fb-432a-abf6-7b1f86168c65"
Authorization: Bearer <token deleted>
--batch_8215457c-c4fb-432a-abf6-7b1f86168c65
Content-Type: multipart/mixed; boundary="changeset_d9097ba9-2d69-40ca-a301-90cf97aafb17"
Content-Transfer-Encoding: binary
--changeset_d9097ba9-2d69-40ca-a301-90cf97aafb17
Content-Type: application/http
Content-Transfer-Encoding: binary
DELETE https://myOrg.sharepoint.com/sites/mySite/_api/web/lists/getByTitle(myList)/items(27) HTTP/1.1
If-Match: *
Accept: application/json; odata=nometadata
--changeset_d9097ba9-2d69-40ca-a301-90cf97aafb17
Content-Type: application/http
Content-Transfer-Encoding: binary
DELETE https://myOrg.sharepoint.com/sites/mySite/_api/web/lists/getByTitle(myList)/items(30) HTTP/1.1
If-Match: *
Accept: application/json; odata=nometadata
--changeset_d9097ba9-2d69-40ca-a301-90cf97aafb17--
--batch_8215457c-c4fb-432a-abf6-7b1f86168c65--
The response I get back for each item to be deleted is 400 Bad Request with each Batch response also containing:
{"odata.error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"Invalid request."}}}
--batchresponse_38add954-a201-4857-a6db-68067eb9bc0a
Content-Type: application/http
Content-Transfer-Encoding: binary
HTTP/1.1 400 Bad Request
CONTENT-TYPE: application/json;odata=nometadata;streaming=true;charset=utf-8
{"odata.error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"Invalid request."}}}
--batchresponse_38add954-a201-4857-a6db-68067eb9bc0a
Content-Type: application/http
Content-Transfer-Encoding: binary
HTTP/1.1 400 Bad Request
CONTENT-TYPE: application/json;odata=nometadata;streaming=true;charset=utf-8
{"odata.error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"Invalid request."}}}
--batchresponse_38add954-a201-4857-a6db-68067eb9bc0a--
I've been digging and have tried a few things:
Tried removing the "Accept: application/json; odata=nometadata" from each changeset
Tried adjusting any newlines after requests content-type/encoding
I have tried executing one item in the batch as a single delete request (works)
compared some notes/examples: (Andrew Connell blog: https://gist.github.com/andrewconnell/dcd89e694475b628d0c7)
Can a helpful eye point out the mistake?
This was a bad interpretation of the documentation on my part.
According to Microsoft's documentation, the section on the Request URL states (emphasis mine):
The request URL consists of the root service URL and the $batch option; for example, https://fabrikam.sharepoint.com/_api/$batch or https://fabrikam.office365.com/api/v1.0/me/$batch.
However, the "root service URL" is a bit misleading, as it's actually supposed to be the site's URL. I would have considered the root service URL:
https://myorg.sharepoint.com
So, in my example above, it's:
POST <siteURL>/_api/$batch
Or, more specific to the example:
POST https://yourorg.sharepoint.com/sites/mySite HTTP/1.1
Thanks for everyone who put some thought into this.

Creating pages on sharepoint site with microsoft graph

Currently I'm trying to create a page on a newly created site with some dummy data. According to https://learn.microsoft.com/en-us/graph/api/sitepage-create?view=graph-rest-beta it should be possible to create a page using json like this:
POST https://graph.microsoft.com/beta/sites/tenant.sharepoint.com%2Cee2667f8-2bae-460e-944b-613773baaa03%2C8c0054a6-6e0e-49cd-be6d-4c4c0aaf644e/pages HTTP/1.1
Authorization: Bearer <token>
User-Agent: Java-Client
Accept-Encoding: gzip,deflate
Accept: application/json, text/json
Content-Type: application/json; charset=UTF-8
Host: graph.microsoft.com
Connection: keep-alive
Content-Length: 167
{"name":"Testpage21.aspx","publishingState":{"level":"published","versionId":"0.1"},"title":"Testpage21","webParts":[{"type":"rte","innerHTML":"<h1>Hello!</h1>"}]}
as you can see nothing fancy. Unfortunatly when issueing this request I receive the following error response:
HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Type: application/json
request-id: 1dba7669-1318-488a-a416-63fddbdfcda1
client-request-id: 1dba7669-1318-488a-a416-63fddbdfcda1
Duration: 833.8091
Strict-Transport-Security: max-age=31536000
Date: Fri, 04 Jan 2019 15:13:15 GMT
Content-Length: 236
{
"error": {
"code": "generalException",
"message": "General exception while processing",
"innerError": {
"request-id": "1dba7669-1318-488a-a416-63fddbdfcda1",
"date": "2019-01-04T15:13:16"
}
}
}
When I remove the webparts property from my initial requests the POST succeeds I get response like this:
{"#odata.context":"https://graph.microsoft.com/beta/$metadata#sites('tenant.com%2Cee2667f8-2bae-460e-944b-613773baaa03%2C8c0054a6-6e0e-49cd-be6d-4c4c0aaf644e')/pages/$entity","eTag":"\"{DA2C2C0C-2222-4F11-917E-7B4BBFE8AC99},3\"","id":"da2c2c0c-2222-4f11-917e-7b4bbfe8ac99","lastModifiedDateTime":"2019-01-04T15:08:12Z","name":"Testpagina2.aspx","webUrl":"SitePages/Testpagina2.aspx","title":"Testpagina2","pageLayout":"Article","parentReference":{"siteId":"ee2667f8-2bae-460e-944b-613773baaa03"},"contentType":{"id":"0x0101009D1CB255DA76424F860D91F20E6C411800A19AB965C0D2B54C82DFCC03DBE6A732","name":"Sitepagina"},"publishingState":{"level":"checkout","versionId":"0.1"}}
But ofcourse I would like to add at least some content ( html ) to the page before I publish it.
Could someone tell me if the creation of pages using Graph is not yet fully functional? Or that I'm missing something.
p.s. what kind of webparts are available?
Unfortunately we have a bug in our docs (assigned to be fixed), the "innerHTML" property should be wrapped in a "data" property like the properties of other web parts. Here's what your payload should look like:
{
"name":"Testpage21.aspx",
"publishingState":{"level":"published","versionId":"0.1"},
"title":"Testpage21",
"webParts": [{
"type":"rte",
"data": {
"innerHTML":"<h1>Hello!</h1>"
}
}]
}
In terms of what web parts are available any part should work but we have not documented the data structures associated with them for the current Beta release. That generally makes the API most useful with your own custom web parts where you already know what properties you need to have in the data block.

Using Acumatica REST API with Microsoft Flow

Has anyone tried using the Acumatica REST APIs with Microsoft Flow?
I tried it a few weeks ago using Sergey's instructions (click here) and it worked fine.
But now I'm getting the following message on the second step.
{
"message": "You are not logged in."
}
The first step is where I authenticate (just like in Sergey's instructions), then I pass the headers from the first step to the second step (just like in Sergey's instructions), but somehow the second step doesn't think that I'm logged in.
Any ideas?
Here are some screenshots (the only thing I changed for the screenshot is the password):
https://i.imgur.com/uD3CpCa.png
https://i.imgur.com/CZ6XLsW.png
https://i.imgur.com/8XB1LT2.png
Here are the Headers Outputs from the first call (HTTP):
X-Handled-By
Acumatica-PX.Export/AuthenticationManagerModule
Set-Cookie
ASP.NET_SessionId=0koh1ysshqsfmzr0srib2s5z; path=/; HttpOnly,UserBranch=16; path=/,Locale=Culture=en-US&TimeZone=GMTM0800A; expires=Sat, 18-Nov-2017 17:51:27 GMT; path=/,.ASPXAUTH=880C71F4E1A76C36E7E468337C01BC9E6E4C898E1977BAAAF2A35F7217B1D9132794A9547071508A35A2D4B9132DC4B55E86DD6E9C9B8D46CAECE39D74CC9B44BDD47E7C0D836D22D8F4EEFAF8142A9987418B8003EFF5B340DF735E7F8F36EDE5D25300D887E4DADEB0A80B707D87F6B0D32437; path=/; HttpOnly
Server
Microsoft-IIS/7.5
X-Powered-By
ASP.NET
Date
Wed, 15 Nov 2017 17:51:27 GMT
Content-Length
0
Here are the Headers Inputs from the second call (HTTP 2):
{
"X-Handled-By": "Acumatica-PX.Export/AuthenticationManagerModule",
"Set-Cookie": "ASP.NET_SessionId=0koh1ysshqsfmzr0srib2s5z; path=/; HttpOnly,UserBranch=16; path=/,Locale=Culture=en-US&TimeZone=GMTM0800A; expires=Sat, 18-Nov-2017 17:51:27 GMT; path=/,.ASPXAUTH=880C71F4E1A76C36E7E468337C01BC9E6E4C898E1977BAAAF2A35F7217B1D9132794A9547071508A35A2D4B9132DC4B55E86DD6E9C9B8D46CAECE39D74CC9B44BDD47E7C0D836D22D8F4EEFAF8142A9987418B8003EFF5B340DF735E7F8F36EDE5D25300D887E4DADEB0A80B707D87F6B0D32437; path=/; HttpOnly",
"Server": "Microsoft-IIS/7.5",
"X-Powered-By": "ASP.NET",
"Date": "Wed, 15 Nov 2017 17:51:27 GMT",
"Content-Length": "0"
}
Here are the Headers Outputs from the second call (HTTP 2):
X-Handled-By
Acumatica-PX.Export/AuthenticationManagerModule
Date
Wed, 15 Nov 2017 17:51:27 GMT
Set-Cookie
ASP.NET_SessionId=dklemj2usv2zveyc3acxnhm5; path=/; HttpOnly
Server
Microsoft-IIS/7.5
X-Powered-By
ASP.NET
Content-Length
36
Content-Type
application/json; charset=utf-8
I had one previously and the difference that I see between your and mine is that your login post doesn't have any headers.
Mine had :
Accept application/json
Content-Type application/json
Here is a screenshot of my working flow : https://imgur.com/a/trgBa
EDIT :
After playing with this a bit more I have found a way off making this work. though it is using OAuth authentication instead of cookie based authentication.
Here is how :
I first created a connected application on the screen of the same name in acumatica
Of the following type : Ressource Owner Password Credentials
I also created added a shared secret while taking note of its value (it is only showed once).
I created the first http call in flow using the following information
URL : https://"Acumatica ERP instance URL"/identity/connect/token
Header : Content type / application/x-www-form-urlencoded
Body : grant_type=password&client_id=Value1&client_secret=Value2&username=Value3&password=Value4&scope=api
Value1 : ID of the connected application created in step 1
Value2 :Value of the shared secret saved from step 1. If lost just remove and add another secret. just be careful no one else is using that secret
Value3 : Username of existing account
Value4 : Password of account specified in value 3
Create the second HTTP call that will do the web service request
URL : https://"Acumatica ERP instance URL"/entity/Default/17.200.001/Case
Header : Authorization / bearer substring(substring(string(body('HTTP_2')),indexOf(string(body('HTTP_2')),':'),34),2,32)
Body : a normal REST API body for the requested operation
The Substring is only separated by a space in the header
Here are image representing the 2 HTTP calls

PDF.JS Cross Domain

I am attempting to use PDF.JS in order to render user's PDFs in the browser.
We store the PDF files in Azure Blob Storage and we have CORS & SAS to allow our front-end to interact directly with Blob for upload/download.
I have tested our setup with Chrome, Firefox, and Safari, and Chrome is the only browser to fail retrieving the file. The errors I get are related to unsafe headers, the exception below I know results from the inability to read the Content-Range header.
Refused to get unsafe header "Content-Encoding"
Refused to get unsafe header "Content-Range"
Uncaught TypeError: Cannot read property '1' of null
at NetworkManager_onStateChange [as onStateChange]
The response headers from Azure look like:
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Accept-Ranges,Content-Range,Content-Encoding,Content-Length
Cache-Control: max-age=1209600
Content-Disposition: attachment; filename=tracemonkey.pdf
Content-Length: 65536
Content-Range: bytes 0-65535/1016315
Content-Type: application/pdf
Date: Tue, 09 May 2017 15:31:33 GMT
Etag: "0x8D49632DD6406EC"
Last-Modified: Mon, 08 May 2017 16:54:17 GMT
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-blob-type: BlockBlob
x-ms-lease-state: available
x-ms-lease-status: unlocked
x-ms-request-id: 56258985-0001-0062-15d9-c8130c000000
x-ms-server-encrypted: false
x-ms-version: 2015-12-11
This is our setup for Blob Storage
Can anyone help me figure out what additional configuration I need to provide to Azure Blob Storage to get this working in Chrome?
set this rules,working on same issue
<Cors>
<CorsRule>
<AllowedOrigins>http://www.contoso.com, http://www.fabrikam.com</AllowedOrigins>
<AllowedMethods>PUT,GET,POST</AllowedMethods>
<AllowedHeaders>x-ms-meta-abc,x-ms-meta-data*,x-ms-meta-target*</AllowedHeaders>
<ExposedHeaders>x-ms-meta-customheader,x-ms-meta-data*</ExposedHeaders>
<MaxAgeInSeconds>200</MaxAgeInSeconds>
</CorsRule>
<Cors>
So this was a bit of PEBKAC. I will leave my settings here for anyone else that comes along. We had an application running that set ExposedHeaders=* and AllowedHeaders=* every time we would new our blob service class. So, every time I went into our portal to update the configs, the app would come in after me and change it back.
The settings that work are as follows:
{
Cors: {
CorsRule: [
{
AllowedOrigins: [‘*’],
AllowedMethods: [‘GET’, ‘PUT’, ‘DELETE’],
AllowedHeaders: [‘Accept-Ranges’, ‘Content-Encoding’, ‘Content-Length’, ‘Content-Type’, ‘Range’, ‘Authorization’,'x-ms-blob-content-type', 'x-ms-blob-type', 'x-ms-version'], // x-ms headers for upload
ExposedHeaders: [‘Accept-Ranges’, ‘Content-Range’, ‘Content-Encoding’, ‘Content-Length’, ‘Content-Type’],
MaxAgeInSeconds: Constants.timeout,
},
],
},
}
Thanks #async5 for the help.

HttpResult or HttpError with response dto does not get serialized into body

i am trying to return a BadArguments Error along with a custom DTO in the body:
var result = new HttpResult(response, "application/json", HttpStatusCode.BadRequest);
I have tried to use HttpError, HttpResult, setting the response by hand etc etc but i get only
HTTP/1.1 400 BadRequest
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: ServiceStack/3,22 Win32NT/.NET
X-Powered-On: ITDEVELOP36-PC
Test-Header-ValidationError: TestValidationError
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 26 Feb 2015 10:36:12 GMT
b
Bad Request
0
No body, no content type is set. What am i missing?
ServiceStack version is 3.3.6.29935.
After poking a while i have found that the ServiceStack framework works just fine. Even in the older version we are using.
The issue exist only when the web.config enables the section.
After removing this section all worked well.

Resources