dev_appserver.py locally rejects PATCH requests but accepts it on deployed - google-app-engine

I've got an app based on djangoappengine, Backbone.js and Django REST Framework that uses PATCH requests to update models via {patch: true} on a model.save call.
I've found that when testing locally the dev_appserver returns:
ERROR 2014-02-19 04:37:04,531 dev_appserver.py:3081] code 501, message Unsupported method ('PATCH')
INFO 2014-02-19 04:37:04,532 dev_appserver.py:3090] "PATCH /api/posts/5707702298738688 HTTP/1.1" 501 -
Yet when I deploy it and access it through appspot the server happily accepts the request. Which forces me to deploy every time I make a change and want to test it.
I'm running the latests version (1.89) of the Python SDK, and found and old fixed issue that seems to tackle it but it seems other people have had it.
I tried this patch but it didn't make a difference. I don't understand why the development server would reject them and not the production server, is there something I need to change?
Thanks.

To update a resource, you can use POST with the x-http-method-override to patch. This is a valid RESTful operation and using POST will be more compatible with firewall and older user agents. The data in the request should indicate what is to be updated.
var url = '/api/posts/5707702298738688'
var patch_ops = [
{ "op": "replace", "path": "/properties/", "author": text}
{ "op": "add", "path": "/replies/", {"author": text, "comment":"blah"}}
/*
{ "op": "remove", "path": "/a/b/c" },
{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
{ "op": "replace", "path": "/a/b/c", "value": 42 },
{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
{ "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
*/
];
var xhr = jQuery.ajax({
type: "POST",
beforeSend: function (request)
{
request.setRequestHeader("X-HTTP-Method-Override", "PATCH");
},
url: url,
data: my_json_string,
dataType:"json",
success: function(data) {
return data;
},
error: function(xhr, textStatus, error){
return error;
}
});
Server handler:
def post(self, object_name):
if self.request.headers['x-http-method-override'] == 'PATCH':
# update according to patch operations
patch_ops_str= self.request.body.decode('utf-8')
try:
patch_ops = json.loads(new_area_geojson_str)
except:
self.response.set_status(400)
return self.response.out.write('{"status": "error", "reason": "JSON Parse error" }')
else:
self.response.set_status(405)
return self.response.out.write('{"status": "error", "reason": "post not accepted without x-http-method-override to PATCH" }')
Adapted from Please do not patch like an idiot

Related

How To Get Google User Profile Info Using Access Token From OAuth?

I am using ReactJS on the frontend: I successfully retrieved the access token from Google's Oauth service, but it doesn't give me any profile information for the 'current user'.
I tried using the /userInfo endpoint, ?access_token={my_access_token} query str, and some other solutions but I keep getting weird errors.
Currently I have:
const { access_token, refresh_token } = res.data; // now I have valid access_token
let userInfo = await axios.get("https://www.googleapis.com/oauth2/v3/userinfo",
{
headers: {
Authorization: `Bearer ${access_token}`
}
}); // ERROR WHEN MAKING THIS CALL.
My specific 401 error is as follows:
If there are better ways of getting user info (such as first/last name, email, etc. some sort of unique ID) please let me know.
You shouldnt rely on the user info endpoint to get user profile informaiton. As long as you are requesting the profile scope from the user, or even email. you should go though the People api. This will give you access to all of the users profile data.
GET https://people.googleapis.com/v1/people/me?personFields=names HTTP/1.1
Authorization: Bearer [YOUR_ACCESS_TOKEN]
Accept: application/json
response
{
"resourceName": "people/117dd2004755326722775346",
"etag": "%EgUBAi43PRoEAQIFBddyIMR3BzQkR2cnI1ZGc9",
"names": [
{
"metadata": {
"primary": true,
"source": {
"type": "PROFILE",
"id": "117200155326727753146"
}
},
"displayName": "Linda Lawton",
"familyName": "Lawton",
"givenName": "Linda",
"displayNameLastFirst": "Lawton, Linda",
"unstructuredName": "Linda Lawton"
},
{
"metadata": {
"source": {
"type": "CONTACT",
"id": "3faa96eb0118baa4be"
}
},
"displayName": "Linda Lawton",
"familyName": "Lawton",
"givenName": "Linda",
"displayNameLastFirst": "Lawton, Linda",
"unstructuredName": "Linda Lawton"
}
]
}

Change value from api response React

From a request call to the marvel API I receive the following
{
"id": 1011334,
"name": "3-D Man",
"description": "",
"modified": "2014-04-29T14:18:17-0400",
"thumbnail": {
"path": "http://i.annihil.us/u/prod/marvel/i/mg/c/e0/535fecbbb9784",
"extension": "jpg"
},
How can I change the thumbnail.path to be https instead of HTTP because when I deploy the app I get the warning of mixed content saying it will be change automatically
You can change the value of response after response received. for example:
axios.get('/post?ID=12345')
.then((response) => {
const modifiedResponse = response.data;
modifiedResponse.thumbnail.path =
modifiedResponse.thumbnail.path.replace("http", "https");
// I see you tagged react
this.setState({post: modifiedResponse});
})
Please share more code if it seems my answer is ambiguous.

change the header Content-Type to application/cloudevents+json when publishing to event grid

I'm using the trigger "When a HTTP request is received" to then publish multiple events to the event grid using the "Publish Event" action. The For loop works fine to split up the JSON that gets in and create the event to publish but still that publish fails with
{
"error": {
"code": "UnsupportedMediaType",
"message": "The Content-Type header is either missing or it doesn't have a valid value. The content type header must either be application/cloudevents+json; charset=utf-8 or application/cloudevents-batch+json; charset=UTF-8. Report 'edf36bbd-9221-4882-8a29-2264ffb16d72:3:3/6/2020 2:18:20 PM (UTC)' to our forums for assistance or raise a support ticket.",
"details": [
{
"code": "InvalidContentType",
"message": "The Content-Type header is either missing or it doesn't have a valid value. The content type header must either be application/cloudevents+json; charset=utf-8 or application/cloudevents-batch+json; charset=UTF-8. Report 'edf36bbd-9221-4882-8a29-2264ffb16d72:3:3/6/2020 2:18:20 PM (UTC)' to our forums for assistance or raise a support ticket."
}
]
}
}
I assume that the header from the input is used when publishing so I tried to change the header when publishing by changing the header in the Publish_Event block as follows (directly in code view as it is not supported in the UI) so I get the following (headers part is added):
"Publish_Event": {
"inputs": {
"body": [
{
"data": "#items('For_each_2')",
"eventType": "company-location",
"id": "ID : #{items('For_each')['businessId']}",
"subject": "Company Location changed"
}
],
"headers": {
"Content-Type": "application/cloudevents+json; charset=utf-8"
},
"host": {
"connection": {
"name": "#parameters('$connections')['azureeventgridpublish']['connectionId']"
}
},
"method": "post",
"path": "/eventGrid/api/events"
},
"runAfter": {},
"type": "ApiConnection"
}
But this is not working neither. Didn't find an action to make the change.
My full flow looks like this :
and as test data I have the following JSON I use to send with postman (a bit simplified):
[
{
"id": 3603,
"businessId": "QQTADOSH",
"locations": [
{
"id": 5316,
"businessId": "A-yelr3g"
},
{
"id": 5127,
"businessId": "A-c7i8gd"
},
{
"id": 5403,
"businessId": "A-fjdd2y"
},
{
"id": 6064,
"businessId": "A-rqvhz8"
}
]
},
{
"id": 3118,
"businessId": "Cr11_Macan_111qa",
"locations": [
{
"id": 4563,
"businessId": "A-3bv860"
}
]
}
]
Looks like the Official Event Grid Publish Connector doesn't support Cloud Events Schema.
You can set the topic to accept Event Grid Schema but I believe this is possible only at the time of creation.
Its best to open a feature request on UserVoice to add support for this and in the meantime, a workaround would be to use an HTTP Action to Post to Custom Topic instead.
But do note that the workaround would involve building the event payload to send (and things like fetching the access key from Key Vault instead of storing it in your workflow directly).

Ask for how to get user profile after callback

My web application is using Single Sign On (SSO) service from IBM Bluemix. This is the credentials info of my SSO service:
{
"SingleSignOn": [
{
"credentials": {
"secret": "MYSECRET",
"tokenEndpointUrl": "https://adminwebsso-jjjfvxi6wy-cq17.iam.ibmcloud.com/idaas/oidc/endpoint/default/token",
"authorizationEndpointUrl": "https://adminwebsso-jjjfvxi6wy-cq17.iam.ibmcloud.com/idaas/oidc/endpoint/default/authorize",
"issuerIdentifier": "adminwebsso-jjjfvxi6wy-cq17.iam.ibmcloud.com",
"clientId": "MYCLIENTID",
"serverSupportedScope": [
"openid"
]
},
"syslog_drain_url": null,
"volume_mounts": [],
"label": "SingleSignOn",
"provider": null,
"plan": "professional",
"name": "VA-Admin-Console-R1-SSO",
"tags": [
"security",
"ibm_created",
"ibm_dedicated_public"
]
}
]
}
From my Application, I redirect to Login page of IBM like URL:
https://adminwebsso-jjjfvxi6wy-cq17.iam.ibmcloud.com/idaas/oidc/endpoint/default/authorize?response_type=code&client_id=MYCLIENTID&redirect_uri=http://localhost/callbackā‰»ope=openid%20openid
After login success IBM redirect to my web application, I can get parameter "code" from callback URL (http://localhost/callback?scope=openid&code=bngM6aV5cYHAvhv7wLAM5QSWFDARn7).
From there, I use the "code" to to get user profile. I have try to use AJAX to get user profile:
var settings = {
"async": true,
"crossDomain": true,
"url": "https://idaas.ng.bluemix.net/sps/oauth20sp/oauth20/token",
"method": "POST",
"headers": {
"content-type": "application/x-www-form-urlencoded",
"authorization": "Basic RXhhbXBsZV9BcHBJRDpWUFlndEdXRlRvYVpZSUNTRzhJeVZFV000bUZicGpsU2t4RlRRbzlySkRGZDdzckc=",
"cache-control": "no-cache"
},
"data": {
"client_secret": "MYSECRET",
"grant_type": "authorization_code",
"redirect_uri": "http://localhost/callback",
"code": "bngM6aV5cYHAvhv7wLAM5QSWFDARn7",
"client_id": "MYCLIENTID"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});
From ajax post above, I have tried to use the "code" from callback, but I've got an error message:
500 Error: Failed to establish a backside connection
I've got stuck here and don't know how to get user profile from SSO.
With in the SSO Service there are some inbuilt macros that can be used to get the user name, for more information please see.
https://console.bluemix.net/docs/services/SingleSignOn/customizing_pages.html#customizing_pages
#USERNAME# The user ID of the authenticated user.

Post data on Kinvey DataStore with Business Logic

I just started to work with Kinvey and I'm having some issues to POST data via REST api.
If I go in the datastore I'm able to save it, but it doesn't work when sending via POST.
To post data, I'm using the URL "/appdata/APP_KEY/DATASTORE/" and sending Authorization, X-Kinvey-API-Version and Content-Typein the Headers.
And I get back "An unknown internal error occured in the processing of the Business Logic code."
When I add my business logic with App Engine (for a while, it just returns status=200 to Kinvey), I have the same error:
{
"error": "BLInternalError",
"description": "The Business Logic script did not complete. See debug message for details.",
"debug": "An unknown internal error occured in the processing of the Business Logic code."
}
Does anyone have any idea where am I doing wrong?
For the last, even when I call Kinvey via GET the method that Kinvey calls App Engine is POST, is there a way to change it?
Despite the errors, I always have the log of access in Google App Engine.
Thank you!
I sent an email to Kinvey support and they helped me a lot.
Some of my mistakes:
The JSON that I was returning back was wrong [*];
I didn't add in the header of my response the Content-Type and status.
Now it works perfectly!
[*] The JSON that I send back in the body of the response is:
{
"request": {
"method": "<redacted>",
"username": "<redacted>",
"entityId": "<redacted>",
"collectionName": "<redacted>",
"headers": {
"connection": "<redacted>",
"host": "<redacted>",
"x-forwarded-for": "<redacted>",
"x-forwarded-port": "<redacted>",
"x-kinvey-api-version": "<redacted>",
"x-real-ip": "<redacted>",
"authorization": "<redacted>",
"x-forwarded-proto": "<redacted>"
},
"body": "<redacted>",
"params": "<redacted>"
},
"response": {
"complete": True,
"headers": {
"x-powered-by": "<redacted>",
"x-kinvey-api-version": "<redacted>",
"x-kinvey-request-id": "<redacted>"
},
"body": {},
"error": None,
"statusCode": 200
}
}
Thanks again to Brian in the Kinvey support!
[]'s

Resources