I have an Azure Function app running which works great, I send a JSON body through Postman and it works fine.
I am now trying to add Azure API Management in front of this for the added features. This has now stopped sending the JSON body through to the Function App. I get a response from the function app through the API Management with a response, basically telling me it is expecting something in the body.
As you can see, the body is null.
Am I missing something on the API Management side? I'm setting the header Content-Type to application/json
Please help me! :) I'm pulling my hair out and I bet I have just missed something obvious.
I have figured out that if you submit a GET request. It does not send a body. I have changed this to POST and it worked perfectly.
Related
I have a problem with handling POST requests in Google Apps Script. I've created simple project with following functions:
function doGet(e){
return ContentService.createTextOutput("test").setMimeType(ContentService.MimeType.TEXT);
}
function doPost(e){
return ContentService.createTextOutput("test").setMimeType(ContentService.MimeType.TEXT);
}
When I try to send a GET request from postman I get correct response - as expected. However when I try to send POST request I get 405 Method not allowed and HTML error page in response. In deployment settings I set that it should execute as me and should be accessible to everyone.
What am I missing? How to make POST requests work with Google Apps Script?
EDIT:
So as Heiko Theißen wrote below there is 302 redirect at first.
As I can see Postman follows that redirect and sends POST once again to new URL but this request fails and I still don't know why unfortunately. I can see in security section that there is header Allow: HEAD, GET.
I cannot see any preflight request from Postman (as TheMaster suggested).
About reproducibility: I've pasted complete content of google apps script, and I mentioned that I am making request from postman. Here is link to current deployment of that script: https://script.google.com/macros/s/AKfycbyHdVpclM7pH1BB3IzwNjtcH07DF75H8ldqeLQCwQnX71lMs371g-UO-i8JaI5_zRqrDw/exec
Also here is screenshot from Postman - I'm just sending empty POST request without any custom headers. Tried also sending plain text or json as payload but results were the same each time.
So back to my original question: How can I receive POST request successfully in google apps script deployed as Web App?
I make it workable from postman by disabling the annotated option from settings.
If the preflight explanation given by TheMaster does not solve your problem, the following might help:
Requests to Google Apps Script always happen in two stages: The first request draws a redirection response to a generated URL, and the second request to that URL draws the response that you programmed (the text output "test").
When the first request is a POST request, the redirection response has status "302 Found", and the specification is ambiguous about what method the second request should have:
Note: For historical reasons, a user agent MAY change the request
method from POST to GET for the subsequent request. If this
behavior is undesired, the 307 (Temporary Redirect) status code
can be used instead.
Google Chrome makes the second request as a GET request (without repeating the POST payload, which the server already knows under the generated URL) and this works.
However, if your browser or Postman client does not change the method and makes the second request again as a POST (and your screenshot shows this is true), the server does not accept this and responds with "405 Method Not Allowed".
In other words: Google Apps Script expects the second request to be a GET request, but not all clients behave like that, because the specification is ambiguous at this point. Workarounds:
You can influence the behavior of Postman so that it does not preserve the POST method between the first and second request. See here.
Google Apps Script could avoid the ambiguity by responding to the first request with "303 See Other", but it does not. Perhaps create an issue for that?
I’m going through the wizard to create a custom connector in Power Apps to call a simple Get operation in Azure APIM. I can call the API fine using Postman, Fiddler and CURL. However, when I try to test the connector using the test tab I’m getting a 200 OK but the response body is empty:
It’s worth mentioning that this issue, with empty response body, occurs only for APIs in Azure APIM. If I hit the backend API, hosted in Azure App Service, without going through Azure APIM I’m receiving a response body. I have tested with other public APIs on the internet which works fine as well. The problem with empty response seems to have something to do with the integration between Power Apps and Azure APIM.
Any assistance is highly appreciated.
With the help of Azure Application Insights logs, I discovered that this is ralated to CORS. To resolve the issue, I added the https://flow.microsoft.com to Azure APIM CORS policy to allow calls from the PowerApps test console to come through, like so:
EDIT 2 - I have now provided my own answer to the issue - any further thoughts or inputs would still be appreciated
EDIT 1 - POTENTIAL RELEVANT INFORMATION:
I've found this footnote at the bottom of the Content Service documentation page that says:
For security reasons, content returned by the Content service isn't served from script.google.com, but instead redirected to a one-time URL at script.googleusercontent.com. This means that if you use the Content service to return data to another application, you must ensure that the HTTP client is configured to follow redirects. For example, in the cURL command line utility, add the flag -L. Check the documentation for your HTTP client for more information on how to enable this behavior.
This seems relevant as I am using ContentService to serve data to Strava's GET request - would this not mean that the response it receives comes from a different URL and hence not from the specified callback URL?
I've been trying to use Google Apps Script to create a webhook subscription to Strava and I feel like I'm extremely close to figuring it out, but I've encounter one last hurdle that I can't seem to pass.
The documentation for creating a webhook subscription to Strava is listed here and I've reached the stage at which I'm making a POST to the Strava API requesting a subscription. Strava then sends an HTTP GET request to my callback_url that I've specified which contains some parameters - most important of which is the hub.challenge parameter. This param must then be sent back within 2 seconds by my callback address in order for the link to be validated. This is where I'm having some grief.
function doGet(e) {
var hubChal = e.parameter["hub.challenge"];
var result = {
"hub.challenge": hubChal
};
return ContentService.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON);
}
Above is my current function that is dealing with incoming GET requests.
In the documentation it states:
Your callback address must respond within two seconds to the GET request from Strava’s subscription service. The response should indicate status code 200 and should echo the hub.challenge field in the response body as application/json content type: { “hub.challenge”:”15f7d1a91c1f40f8a748fd134752feb3” }
However, when I send the POST to the webhook subscription API I receive this response on Postman:
{
"message": "Bad Request",
"errors": [
{
"resource": "PushSubscription",
"field": "callback url",
"code": "GET to callback URL does not return 200"
}
]
}
I checked through the troubleshooting advice that is offered on the doc page, an element of which gives a sample GET request for you to send yourself to see what your callback address offers in return:
Check that the response to the above request shows a 200 status and correctly echos the hub.challenge in the JSON body. The response body to the above sample curl request should look like { “hub.challenge”:”15f7d1a91c1f40f8a748fd134752feb3” }
With the following dummy GET request:
{your-callback-url}?hub.verify_token=test&hub.challenge=15f7d1a91c1f40f8a748fd134752feb3&hub.mode=subscribe
Plugging in my callback url and sending a GET request via Postman returns the following to me:
{
"hub.challenge": "15f7d1a91c1f40f8a748fd134752feb3"
}
Along with showing a 200 OK Status code and in well under 2 seconds.
I really can't see what I've done incorrectly here, as it seems like I'm fulfilling the criteria laid out to set up a subscription. It's worth mentioning that I'm not very familiar with Google Apps Script, so it's entirely possible and even likely that I'm missing something basic, but I can't see it for the life of me.
I've gone through all of the troubleshooting advice and haven't been able to find an answer online despite an entire afternoon and evening of searching yesterday. Any help would be enormously appreciated - thanks.
I believe I've finally figured out my issue and unfortunately it seems it is not possible to set up a webhook subscription to Strava using Google Apps Script - at least not whilst using ContentService to serve data to Strava GET requests.
At the end of the ContentService documentation it says:
For security reasons, content returned by the Content service isn't served from script.google.com, but instead redirected to a one-time URL at script.googleusercontent.com. This means that if you use the Content service to return data to another application, you must ensure that the HTTP client is configured to follow redirects. For example, in the cURL command line utility, add the flag -L. Check the documentation for your HTTP client for more information on how to enable this behavior.
The problem with this is that Strava expects and will only accept a 200 status code attached to the response to its GET request, however ContentService sends a 302 redirect to this one-time URL. I was able to verify this in Postman by turning off "Automatically follow redirects" in the request settings of my dummy GET request:
https://i.stack.imgur.com/vAvIm.png
Since I have auto redirect enabled by default on Postman, I wasn't seeing the 302 at any point when sending my own requests, leading to everything appearing to be in order.
If there is a way around this ContentService issue then please do inform me, as the outcome of this is that I'm now going to have to poll Strava for new data (booo) which will make my finished product significantly more clunky.
Hopefully this post will now stand to help anyone else who finds themselves with my issue in the future and will save them a few days of confusion!
I am not familiar with Goole Apps Script (very cool, by the way!), but it sounds like you have Strava webhooks well understood.
It sounds like your doGet method is returning something other than 200. Do you have a logging feature that can output what the doGet method is being sent, what it's sending back, etc?
If you haven't already, you may want to check out the Strava tutorial on subscribing to webhooks using Node, Express and Ngrok. A few extra steps, but fairly easy to follow and debug.
I'm testing a REST service provided by a vendor and I'm using Postman client. Initially if I tried to make service call with necessary authorization headers, the client spits out a response (not from the service but Postman) where it says something similar to cannot get a response. But once I attempt the same GET request through Chrome, a username and password is prompted from the browser and once I provide that the JSON response is shown in browser screen.
Once that is done , when I attempt the same request or other request from Postman it works fine and gives me response JSON from service.
Could someone please help me understand what happens here, thanks.
I have written a mosync application that interacts with a REST we service. I am using the AMDownload package. Wat is the right way to send the json payload required by the REST API?
The HTTP 400 Bad Request perhaps happens because the MoSync Android runtime messes up the URL, causing the server to return this error. Alternatively, perhaps the MoSync Android runtime considers the URL to be wrong, and sends back the HTTP 400 Bad Request.
Is it possible for you to test on an Android device? To see if the result is the same.
Also, is it possible to find the exact URL/data sent to the server? Perhaps using some network monitor software. If you have access to the server, can you see the request it receives? If you would enter the same request in a client like the Firefox RESTClient, do you get the same response?