I am currently using Google Cloud Run to deploy an API and although everything was working fine I am now having quite a hard time understanding an error I get.
I created the API on python3 using FastAPI, the Location model is based on Pydantic's BaseModel.
To illustrate it I have defined a test route as follow :
class Location(BaseModel):
lat: float
lng: float
#router.get('/test_404')
async def test_404(origin: Location = Body(...),
destination: Location = Body(...)):
print(origin)
print(destination)
return {'res': 'ok'}
The route should take two arguments in the request's body : origin and destination, and it does but only when I deploy it locally.
This :
url_local = "http://0.0.0.0:8080/test_404"
data = {
'origin': {'lat': 104, 'lng': 342},
'destination': {'lat': 104, 'lng': 342}
}
resp = requests.get(url_local, json = data)
print(resp.text)
Outputs :
'{"res":"ok"}'
The issue arises when I deploy the same service on Cloud Run. All of my other routes work fine but here is the output I get when I use the code above with the container url :
<!DOCTYPE html>\n
<html lang=en>
<meta charset=utf-8>
\n
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
\n <title>Error 400 (Bad Request)!!1</title>\n
\n <a href=//www.google.com/><span id=logo aria-label=Google></span></a>\n
<p><b>400.</b>
<ins>That’s an error.</ins>
\n
<p>Your client has issued a malformed or illegal request.
<ins>That’s all we know.</ins>
This is an error triggered by google and that does not let my request reach the service (no log entry)
I've searched online but did not find what causes this error. What am I missing ?
Thank you very much
It might be related to this post, where a user experiences a similar message. After some reading, and seeing your example, I think the solution lies in the REST best practices.
Strictly speaking, a GET request should not send any data when doing the request, other than anything incorporated within the URI. Technically, everything is possible, but you should use query parameters instead of sending a body.
Some API wrappers (like Cloud Run), may not accept this behaviour, while in your local test it may seem to work. Other API wrappers may just accept a body with a GET request. I would recommend sticking to the REST best practices and you are fine.
Related
I'm using a node soap client to connect to the Bing Ads API and I log the URL within the sendRequest() method:
https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc?wsdl
Which is correct according to the Bing docs here.
But when I get the error output (after the code hangs) it's a different URL. The entire error is:
Error: Invalid WSDL URL: https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc?xsd=xsd1
Side by side of the two URLs:
https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc?wsdl
https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc?xsd=xsd1
It looks like the only difference is that wsdl in the correct URL is being replaced by xsd=xsd1.
Also, I know very little about SOAP APIs so I'm just trying to figure out what is happening.
Why is the URL being altered?
i'm integrating the docusign api with my angular application, everything is working good, i created a proxy configuration in order to do the api calls, im using the demo url since i have a demo developer account.
The problem is that when i run my program in local (using localhost) the authentication token is successfully returned by the oauth call but when i upload my program on an external domain the same call returns me an html with irrelevant information with status 200 OK.
I tried to search this on google but i can't find nothing good.
What should i do?
this is the error i get:
ERROR qm
error: {error: SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse ()
at XMLHtt…, text: "<!doctype html>↵↵↵ <meta ch…b0a19788ec.js" defer="">↵↵"}headers: DmlazyInit: ()=> {…}lazyUpdate: nullnormalizedNames: Map(0) {}proto: Objectmessage: "Http failure during parsing for http://frontendly.it/oauth/token"name: "HttpErrorResponse"ok: falsestatus: 200statusText: "OK"url: "http://frontendly.it/oauth/token"proto: Bm
The OAuth call you are making has a parameter called redirectUri.
Look for &redirect_uri= in the URL.
You have to change that for each location, if you put this in a domain - then you cannot use localhost in there.
This URL has to match exactly to where you deployed your application.
For the second call, make sure to make it a POST, not GET, add the headers like this: (more information)
curl --header "Authorization: Basic NWMyYjhkN.....FhODg2MQ=="
--data "grant_type=authorization_code&code=eyJ0eXAi.....QFsje43QVZ_gw"
--request POST https://account-d.docusign.com/oauth/token
I started using the Azure Maps API on a project using Logic Apps (Azure). All of a sudden the HTTP action stopped working and I am getting a 400 BadRequest Error.
"error": {
"code": "400 BadRequest",
"message": "Bad request: one or more parameters were incorrectly specified or are mutually exclusive."
However, when I call the same API using Postman or my browser, it works fine.
API: https://atlas.microsoft.com/search/fuzzy/json?api-version=1.0&subscription-key=xxxxxxxxxxxxxxxxxxxxxxxxxxx&query=2 5 Donlands Ave 4 Toronto Toronto &countrySet=Ca&maxFuzzyLevel=2&limit=1
As I mentioned, this was working and all of a sudden started failing on Logic Apps without making any changes.
I exactly have the same issue.
I use address rest api to retrieve cities from postal code.
Sample :
https://atlas.microsoft.com/search/address/structured/json?subscription-key=mySubcriptionKey&api-version=1.0&postalcode=35000&countrycode=fr&limit=1
Like you, if I use the query client side, I have a 400 bad request with message :
{
"error": {
"code": "400 BadRequest",
"message": "Bad request: one or more parameters were incorrectly specified or are mutually exclusive."
}
}
Please note that the query is OK for google chrome, but return a 400 bad requests with Brave, Edge (chromium) and Firefox.
Note also that the sample web sdk have the same issue and is not updated.
Currently, I don't have any idea about where is the problem.
Edit : After some investigation, i'm pretty sure that it's a Microsoft issue.
So, I found a workaround.
If I try my query with Firefox, by default I have a 400 and a 200 with chrome.
I compare the header and the issue is with the accept-language.
By default, on Chrome, I Have : Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
On Firefox (Brave, Edge also maybe), I Have : Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Please note the inversion between fr-FR and fr.
If I change my Accept-Language on Firefox from fr,fr-FR to FR-fr,fr. It's working.
If I set my Accept-Language to "fr" only, I still have a 400. Work with "Fr-fr".
So after some test, my conclusion is that atlas have an issue with two letter header accept-langage.
So on my TS/JS code, just add accept-language with 4 letters to work again.
xhr.open('GET', url, true);
xhr.setRequestHeader("Accept-Language", this.acceptLanguage);
xhr.send();
My opinion is that it's a server/ atlas issue, I can't imagine this kind of code evolution from Microsoft ^^
I have used the Crossref REST API where I just send it a query in a browser address bar, which then returns results in JSON.
So I send the following URL:
https://api.crossref.org/works?query.bibliographic=Randomized trial of intensive early intervention for children with pervasive developmental disorder&query.author=Groen&rows=1
I was hoping to so the same with the Microsoft REST API, but if I send it:
I get "Access denied due to invalid subscription key".
Can I pass my key via the URL? If so how?
Or is it not that simple.
Does it need other code as well - I can code in PHP if needed, or use jQuery.
Something like:
$(document).ready(function() {
$.ajax({
type:'GET',
url:'https://api.crossref.org/works?query.bibliographic=<?php echo $title ?>&query.author=<?php echo $author ?>&rows=1&select=is-referenced-by-count,author,title,DOI,issn-type,volume,issue,link,page,abstract',
success:function(result) {
var total_results = result.message["total-results"];
}
});
But again, with the Microsoft API - how would I send it the keys?
Thank you.
What is "the Microsoft REST API"? Do you mean Azure API Management? "Invalid subscription key" implies that this is an API hosted in API Management which uses this term to describe its authentication model. The following answer assumes this is the case.
You would need to be registered as a user and be given a subscription key. There is a self-service portal for doing this, which is described by this documentation. It is up to the API's administrator whether you are permitted to self-service or not, so you may or may not be able to do this yourself, or you may have to request the administrator to register you. Further documentation describes a bit how to use the portal.
When you have it, you would apply it as an http header named Ocp-Apim-Subscription-Key, but the name it expects is also configurable and may have been changed, which the administrator would have to tell you.
I finally found the documentation for what I needed (the Microsoft documentation around Azure is a horrendous maze with a lot of stuff that is outdated and broken).
So the documentation is here:
https://msr-apis.portal.azure-api.net/docs/services/academic-search-api/operations/565d753be597ed16ac3ffc03?
I modified the Jacascript example at the bottom of page and came up with:
<!DOCTYPE html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type:'GET',
url:'https://api.labs.cognitive.microsoft.com/academic/v1.0/evaluate?expr=Composite(AA.AuN==%27jaime%20teevan%27)&count=2&attributes=Ti,Y,CC,AA.AuN,AA.AuId',
beforeSend: function(xhrObj){
// Request headers
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","xxxxmykeyxxxxx");
},
success:function(result) {
alert(result.entities[0].Ti);
}
});
});
</script>
</head>
</html>
The query returns all the titles for the author "jamie teevan".
Though in this example I am just outputting the first title via 'alert'. I haven't coded the rest of it yet - just wanted to know if it worked or not at this point.
Now all I need to do is work out the expression to return all the citing documents for a given title + author!! :-/ wish me luck.
I'm just in the process of experimenting with the Azure rest api's in preparation for some work I'm heading into...
Within node.js I'm trying to obtain a list of webspaces hosted by my subscription using the following code...
var websiteOptions = {
hostname: 'management.core.windows.net',
path: '/<<Subscription-ID>>/services/webspaces',
method: 'GET',
pfx: new Buffer(managementCert, 'base64'),
strictSSL: true,
headers: {
'x-ms-version': '2013-06-01'
}
};
websiteOptions.agent = new https.Agent(websiteOptions);
var request = https.request(websiteOptions,function(res){
console.log('Status Code:', res.statusCode);
console.log('Headers:', res.headers);
When executed it returns back with..
<Error xmlns="http://schemas.microsoft.com/windowsazure"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Code>AuthenticationFailed</Code>
<Message>The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.
</Message>
</Error>
The strange thing is that if I replace ..
/<<subscription-ID>>/services/webspaces
with...
/<<subscription-ID>>/services/hostedservices
That specific call works like a charm, returning a list of hosted services - so this leads me to believe that I'm encoding/attaching my management certificate correctly.
I have tried various api versions in the headers without much luck, I have also read various sections of this article without much luck.
So why are my credentials working in one section of the API and not the websties section
What am I missing, I'm sure it's something really simple :|
OK so now I feel daft, and it just goes to show that even big companies can get it wrong..
I have been playing a bit more and decided to drop a forward slash onto the end of the API call for the web spaces endpoint.. and...
Bingo... it worked like a treat!!!
Would have been nice if Microsoft was consistent across it's API endpoints, the hosted services end point for instance didn't need this trailing slash.
Also, accurate error messages would have been nice too, instead of just reporting an invalid credentials exception!!!
As always.. the simple things in life :(