Hi I am trying to push the notification from rest client to android app. I am doing like below -
URL - https://android.googleapis.com/gcm/send
Method - POST
Headers - Authorization: my_server_key
I always get this message
Status Code: 401 Unauthorized
Alternate-Protocol: 443:quic,p=0.002
Cache-Control: private, max-age=0
I am not sure what I am missing & last I am using correct server api key.
Please assist & thanks in advance.
Push notification uses Web Socket. You cannot do this using HTTP protocol unless you have a server side implementation set up to respond to your request through Web Socket.
I set this values in the header then it is working fine for me.
Below is the header key & value.
A) Authorization: & it value likes key=API_KEY
B) Content-Type: application/json
I hope you are done with your request but it will help to others
You have to send like this
In head
-------
Headder Value
Authorization key=your value
Content-Type application/json
In Body
-------
Something like this
{
"registration_ids" : ["Your id"],
"data" : {
"message":"Your message"
}
}
Hope it will help
Related
I'm posting this on my way home, so forgive the lack of code but I'll try to be as detailed as possible and add code when I can tonight. So essentially I have a react native app using redux and axios. A brief review (code to follow) may explain that I'm doing something wrong.
Serviceapi.js
Creates and exports basic axios with base url.
const ServiceApi = axios.create({
baseURL: BASE_URL,
responseType: 'json'
});
AuthReducer.js
On login sets Authorization header manually using the post method. This works on both android and ios the login is returned and I use the authorization header.
return {
type: PERFORM_LOGIN,
payload: {
user: {
name: username
},
request: {
url: '/login',
method: 'post',
headers: {
'Authorization': 'Basic ' + basicAuth
}
}
}
On login, I return the following redux-axios action, you can see that I set the header: Authorization manually, this works great.
// On login success, set the authInterceptor responsible for adding headers
authInterceptor = ServiceApi.interceptors.request.use((config) => {
console.log(`Attaching Authorization to header ${basicAuth}`);
config.headers.common.Authorization = basicAuth;
return config;
}, (error) => {
Promise.reject(error);
});
On logout I clear the interceptor. I chose to add and remove on login and logout instead of always having it there just because. This could be a problem but it was fine for Android
// Clear the auth interceptor
ServiceApi.interceptors.request.eject(authInterceptor);
Again this is all working great on Android. And it looks to be working on ios. When I debug the interceptor it's getting called and setting the header.
But I get back a 403 on ios. After looking at the request in more detail, there is a big difference between the android header in the request and the ios header in the request. The rest of the request object is the same, only the _header object is different between ios and android.
Android Request
_headers:
accept: "application/json, text/plain, */*"
authorization: "Basic <correct base64 value>"
content-type: "application/json;charset=utf-8"
__proto__: Object
IOS Request
_headers:
accept: (...)
authorization: (...)
content-type: (...)
get accept: ƒ ()
set accept: ƒ ()
get authorization: ƒ ()
set authorization: ƒ ()
get content-type: ƒ ()
set content-type: ƒ ()
__proto__: Object
With the differences, setting a breakpoint at looking at the console for error.request._headers.authorization; I get the same "Basic: " contents as the Android header contains.
index.php
The backend service is a php file that does a $_SERVER['PHP_AUTH_USER'] which fails a 403 if not set which is what's happening. I don't have access to the php, I was just told this is what it's using.
Again I apologize for not providing code but i will when I get a chance later. Is there something maybe I have to set extra for ios? Or maybe php for ios needs an extra header?
Code to follow.
EDIT Updated with code, hopefully I didn't leave in any of the encoded login info.
EDIT 2 Upon further investigation this looks like it's related to apache/PHP rather than react-native/axios. I threw together an express server that simulated the same checking that the PHP does:
- Look for the Authorization header
- Print it
- Return back 403 or 200 w/ data based on that
When running pointing at http://localhost:3000 using the exact same app on the emulator I get back what I'm expecting. To add to this, when I'm on the emulator, I can't actually login to the live URL (even though I could on the regular device), I get the same 403 error but this time a little earlier.
EDIT 3
To provide some more information from the server, here are the three requests that I've been able to log:
1) This is from the IOS Emulator iPhone8 against a an express server:
accept:"application/json, text/plain, */*"
accept-encoding:"gzip, deflate"
accept-language:"en-us"
authorization:"Basic <base 64 encoding>"
connection:"keep-alive"
content-length:"0"
host:"localhost:3000"
user-agent:"MobileApp/1 CFNetwork/978.0.7 Darwin/18.5.
2) This is from the same emulator to apache/PHP (5.3.3), we can see there is no Authorization header.
Accept: application/json, text/plain, */*
User-Agent: MobileApp/1 CFNetwork/978.0.7 Darwin/18.5.0
Accept-Language: en-us
Accept-Encoding: br, gzip, deflate
Connection: keep-alive
3) This is from Android to apache/PHP (5.3.3):
authorization: Basic <Base 64 encoding>
Host: api.serviceurl.com
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.12.1
Edit 4
So after playing around and googling for some time, it turns out that the issue is with Zend Framework and fastcgi which automatically removes the Authorization header. The weird thing is that it's only doing it from IOS and not from Android, which makes no sense really.
On thing we noticed in the logs, is that it's accepting the Android and Postman as POST but it's logging the IOS requests as GET. I'm not entirely sure what's up with that, but it seems to be another difference. I've updated the task to have zend as a tag. There are a number of SO articles on resolving this with ReWriteMod on apache/zend so I'll give those a go first and see if it fixes the issue.
** Edit 5**
So far we've attempted to follow the SO articles which ask that that that following be added (Authorization header missing in django rest_framework, is apache to blame?):
SetEnvIfNoCase Authorization ^(.*) -e=PHP_HTTP_AUTH
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
which results in the following:
// IOS
_SERVER[PHP_HTTP_AUTH] = <blank>
_SERVER[HTTP_AUTHORIZATION] = <blank>
// Android
_SERVER[PHP_HTTP_AUTH] = Username
_SERVER[HTTP_AUTHORIZATION] = Basic <Base65 encoded>
_SERVER[PHP_HTTP_PW] = Password
So we know that Header Authorization is getting to Apache, but now it's coming through as blank. There are a few other SO answers I'm researching but the search continues...
Edit 6
Resolved(ish)
Turns out it was a trailing slash required on the request for IOS. I was able to find this link https://github.com/square/retrofit/issues/1037 where the the issue was described as:
For those interested: We are using Django as our backend and by default when you do
not provide a trailing slash on the endpoint Django redirects from the non-slash
endpoint to the slash endpoint.
Now, we aren't using Django, but apparently for our configuration of Zend it was
the same issue - Android was able to re-direct without issue, while IOS was not. Another comment on the task states:
OkHttp strips the "Authorization" header when redirected across hosts (connections)
via a 3xx response from the original host.
Which doesn't seem accurate, since Android was using OkHttp and was working fine. It looked like IOS using Darwin had the issue.
EDIT
I forgot something else from my original post, I also had to change my interceptor from the line config.headers.common.Authorization = ... to config.headers.Authorization = ... which for some reason kept the casing. Original way converted Authorization to authorization, while the latter kept it as Authorization. Not sure if this was an issue, but I made it anyhow.
// On login success, set the authInterceptor responsible for adding headers
authInterceptor = ServiceApi.interceptors.request.use((config) => {
console.log(`Attaching Authorization to header ${basicAuth}`);
config.headers.Authorization = basicAuth;
return config;
}, (error) => {
Promise.reject(error);
});
I cannot believe I spent 5 hours debugging and researching to resolve the issue eventually with a trailing slash! Even when I tried the trailing slash I thought it was a futile attempt but it actually resolved my issue. #kendavidson you're a lifesaver!!
I have been able to establish a channel to receive push notifications from Google Drive by using the method described here Not receiving webhook notification from drive, why?. I am receiving notifications and everything is working fine. My problem is that when I receive the push notifications, I am only getting this information:
Content-Length: 0
Accept: */*
Accept-Encoding: gzip,deflate,br
Connection: Keep-alive
Host: www.domain.com
User-Agent: APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
X-Goog-Channel-Expiration: Thu, 29 Dec 2016 00:00:00 GMT
X-Goog-Channel-Id: 01ecb23c-e718-8674-6ab3-623931741334
X-Goog-Message-Number: 2745870
X-Goog-Resource-Id: hw75x654x56jYhRNkfU5CFEXXXhtlj8
X-Goog-Resource-State: change
X-Goog-Resource-Uri: https://www.googleapis.com/drive/v3/changes?includeRemoved=true&pageSize=100&pageToken=658&restrictToMyDrive=false&spaces=drive&alt=json
According to this documentation, there are some "Change" notifications messages that include a request body. Unfortunately, I have not been able to get the request body.
The script that handles the push notifications has the following logic:
$oldcontent = file_get_contents('notifications.txt');
$newnotsfile = fopen("notifications.txt", "w");
$post = file_get_contents('php://input');
$requestBody = json_decode($post , TRUE); //convert JSON into array
$time = date("Y-M-d H:i:s", time());
fwrite($newnotsfile , "<br><br>---------------- │ Time: ".$time."<br><br>");
foreach (getallheaders() as $name => $value) {
fwrite($newnotsfile , $name.": ".$value."<br>");
}
fwrite($newnotsfile , $requestBody );
fwrite($newnotsfile , "<br><br>");
fwrite($newnotsfile , $oldcontent);
fclose($newnotsfile );
?>
I thought that by using $post = file_get_contents('php://input'); I would capture the request body but the truth is that it is capturing nothing. If I understand correct, I should receive a change resource with the structure detailed here. Is there something wrong that I'm doing or have I understood this wrong? I appreciate any insight that can be given and thanks in advance!
Actually there is no request body which gets sent in the webhook notification. So as soon as changes arrive in the callback url, changes are to be fetched by making a get request to changes resource uri like below
Resource URI : https://www.googleapis.com/drive/v3/changes?includeRemoved=true&pageSize=100&pageToken=895&restrictToMyDrive=false&spaces=drive&alt=json
Or programatically changes can be fetched by using the below code
String pageToken = channelInfo.getCurrPageToken();
List<Change> changes = service.changes().list(pageToken)
.execute().getChanges();
Google push notifications doc could have mentioned this clearly rather than mentioning that the changes come along in the request body which is the reason for confusion
You might want to check the documentation - Push Notifications, this describes how to use push notifications that inform your application when a resource changes.
Watch response
If the watch request successfully creates a notification channel, it returns an HTTP 200 OK status code.
The message body of the watch response provides information about the notification channel you just created, as shown in the example below.
{
"kind": "api#channel",
"id": "01234567-89ab-cdef-0123456789ab"", // ID you specified for this channel.
"resourceId": "o3hgv1538sdjfh", // ID of the watched resource.
"resourceUri": "https://www.googleapis.com/drive/v3/files/o3hgv1538sdjfh", // Version-specific ID of the watched resource.
"token": "target=myApp-myFilesChannelDest", // Present only if one was provided.
"expiration": 1426325213000, // Actual expiration time as Unix timestamp (in ms), if applicable.
}
And if you will check the Understanding the notification message format:
Notification messages for Files and Changes are empty.
The docs also provided samples:
Change notification message for Files resources, which does not include a request body:
POST https://example.com/notifications // Your receiving URL.
Content-Type: application/json; utf-8
Content-Length: 0
X-Goog-Channel-ID: 4ba78bf0-6a47-11e2-bcfd-0800200c9a66
X-Goog-Channel-Token: 398348u3tu83ut8uu38
X-Goog-Channel-Expiration: Tue, 19 Nov 2013 01:13:52 GMT
X-Goog-Resource-ID: ret08u3rv24htgh289g
X-Goog-Resource-URI: https://www.googleapis.com/drive/v3/files/ret08u3rv24htgh289g
X-Goog-Resource-State: update
X-Goog-Changed: content,properties
X-Goog-Message-Number: 10
Change notification message for Changes resources, which includes a request body:
POST https://example.com/notifications // Your receiving URL.
Content-Type: application/json; utf-8
Content-Length: 118
X-Goog-Channel-ID: 8bd90be9-3a58-3122-ab43-9823188a5b43
X-Goog-Channel-Token: 245t1234tt83trrt333
X-Goog-Channel-Expiration: Tue, 19 Nov 2013 01:13:52 GMT
X-Goog-Resource-ID: ret987df98743md8g
X-Goog-Resource-URI: https://www.googleapis.com/drive/v3/changes
X-Goog-Resource-State: changed
X-Goog-Message-Number: 23
{
"kind": "drive#changes"
}
Understanding Drive API notification events
This section provides details on the notification messages you can receive when using push notifications with the Drive API.
You can try out any of the events below at the Push Notifications Playground or download the source from GitHub.
Hope this information helps.
Hope someone could spare time to help a rookie. I have to set up my server and then provide a supplier with the URL of the page which has to be able to receive a HTTP-Post request like the following - For each post received, your page will have to answer with a "+OK", in order to confirm the correct delivery of the notification.
POST /yourpage.php HTTP/1.1
Host: www.yoursite.com
Content-Length: 215
Connection: Keep-Alive
Content-type: application/x-www-form-urlencoded
Accept-Language: it
Cache-Control: no-cache
destination=%2B40757732753&text=sms+test+example&originator=%2B391234567890&date_time=20160606074445
What would be the best way to go about this instruction? I have some basic knowledge of PHP (still learning), so we can use PHP.
Thanks in advance
Marinda
You need learn about global variables in PHP, php has $_POST able to get content sended on body of post and do something with it.
<?php
// this will create a variable with data of destination sent
$destination = $_POST['destination']
...
// just print +OK
echo "+OK"
But if you want send SMS to Mobile, you need use services to send for you, in general has a cost for this and able to send a limited number of SMSs depend your plan.
I hope it help you
Check $_POST variable. It's a kind of special variable for this language. Then, you can:
<?php
$isOK = true;
// Check if POST parameter destination is set and it is not blank, you
// can repeat this validation with all your parameters, changing
// destination by its name.
if (!isset($_POST['destination']) || trim($_POST['destination']) == '') {
$isOK = false;
}
if ($isOK) {
echo "+OK";
}
I'm a building a RESTful API using Zend Framework 2 and Apigility by Zend Framework.
For testing, I use the chrome extension Postman REST-Client.
I can do GET requests and POST requests without problems by sending form-data without problems.
But when I try to do a PUT, PATCH or DELETE request, I get the following error:
{
"type":"http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",
"title":"Unsupported Media Type",
"status":415,
"detail":"Invalid content-type specified"
}
Accept whitelist in Rest-Service-Config of Apigility:
application/vnd.timber-ms.v1+json, application/hal+json, application/json
Content-Type whitelist:
application/vnd.timber-ms.v1+json, application/json
The content-type of the response is application/problem+json
What can I do to fix this and do successfull PUT/PATCH requests?
Is this a problem with Postman or Apigility?
You're getting the 415 error of Unsupported Media Type when Apigility cannot deserialize the data coming from the client. This recently was called out in the documentation.
I suspect your problem is due to the content-type being sent from postman. Pay special attention to the Content-Type Whitelist listed for the service and make sure it contains the content-type you are sending.
For example, if your service has only has application/json in the Content-Type Whitelist and you send the PUT/PATCH with postman as x-www-form-urlencoded, you will get a 415 error of Unsupported Media Type. If you change postman to send the PUT/PATCH with a content-type of application/json and the request body contains valid JSON, Apigility should accept the request.
You can check the content-type postman is sending by clicking on the "Preview" button just to the right of the "Send" button.
I was having a similar issue in Postman with the unsupported media type responses. However, I experienced this response on both PUT and POST requests using my company's API.
I verified that Postman was the problem here and not the request/API in use by running the same request with another similar Chrome extension called Advanced REST Client. I'm not familiar with Apigility, but pretty sure that Postman is the culprit here.
Hoping there is a fix for this issue as Postman and its collections feature is much easier to use than that of Advanced REST Client.
on postman go to normal tab (or other auths tab) and add header:
Content-Type application/json (or any type you need)
make sure that on the raw tab include the json data
{
"type":"http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",
"title":"Unsupported Media Type",
"status":415,
"detail":"Invalid content-type specified"
}
I had the same problem,
My solution was to write my data to [Body] in the [raw] in json format. Like this:
{"message": "UPDATED First Post!"}
And in [Headers] :
[KEY] Content-Type
[Value] application/json
I have successfully gotten an access_token, so it's not a problem with the 3-legged process.
The problem starts when I try to add a new post/activity using the Buzz API...
Here is my request:
POST /buzz/v1/activities/#me/#self?alt=json HTTP/1.1
Host: www.googleapis.com
Connection: close
Accept-encoding: gzip, deflate
User-Agent: Zend_Http_Client
Content-Type: application/json
Authorization: OAuth
realm="",oauth_consumer_key="example.com",oauth_nonce="ce29b04ce6648fbb92efc8f 08c1c0091",oauth_signature_method="HMAC-
SHA1",oauth_timestamp="1277934794",oauth_version="1.0",oauth_token="1%2FcBz o5ckGvCAm3wLWh1SDH3xQNoW--
yek1NVfUa1Qqns",oauth_signature="CUezSiMbvxyN1BTeb3uROlIx8gA%3D"
Content-Length: 86
{"data":{"object":{"type":"note","content":"posting on Buzz"}}}
Here is the response:
{"error":{"errors":[{"message":"Unknown authorization header","locationType":"header","location":"Authorization"}],"code":401,"message":"Unknown authorization header"}}
And here is my base string (the string that the signature gets generated from):
POST&https%3A%2F%2Fwww.googleapis.com%2Fbuzz%2Fv1%2Factivities%2F%40me
%2F%40self&oauth_consumer_key%3Dexample.com%26oauth_nonce
%3D50acc6b7ac48304ae9301134d6988cdb%26oauth_signature_method%3DHMAC-
SHA1%26oauth_timestamp%3D1278065599%26oauth_token
%3D1%252FcBzo5ckGvCAm3wLWh1SDH3xQNoW--yek1NVfUa1Qqns%26oauth_version
%3D1.0
I've even tried this other base string (with the alt=json added in):
POST&https%3A%2F%2Fwww.googleapis.com%2Fbuzz%2Fv1%2Factivities%2F%40me
%2F%40self%3Falt%3Djson&oauth_consumer_key%3Dexample.com%26oauth_nonce
%3Dee8704244623bbcc860bf77bfcadeacc%26oauth_signature_method%3DHMAC-
SHA1%26oauth_timestamp%3D1278069221%26oauth_token
%3D1%252FcBzo5ckGvCAm3wLWh1SDH3xQNoW--yek1NVfUa1Qqns%26oauth_version
%3D1.0
I have tried pretty much everything to get this working - not sure why it always says 'Unknown authorization header'... the header looks fine when compared to other ones that work.
Any ideas?
which endpoint did you use to authorize request token?
developer's guide:
Important: Part of the OAuth process
requires that you direct the user to
the Google Authorization service to
approve access for your application.
Google Buzz requires that you use a
different Authorization service
endpoint, located at
https://www.google.com/buzz/api/auth/OAuthAuthorizeToken.com/buzz/api/auth/OAuthAuthorizeToken.
You should use GET or POST method (depending what request you use). By default Zend uses header-method.
$client->setMethod(Zend_Http_Client::GET);