Service Worker file offline events - push-notification

Google Chrome latest(v55.0.2883.87)
There are various event in that (sw.js)file. Everytime a file got requested fetch event occur. How and when other events occur(sync, push)(web notification api). I want to debug it. Is there any doc available?
Update:
server-key-from-firebase-console
subscription-key-after-subscribing-web-notification
Found how push notification fired--
String url = "https://fcm.googleapis.com/fcm/send";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("Authorization", "key=<server-key-from-firebase-console>");
con.setRequestProperty("Content-Type", "application/json");
String urlParameters = "{\"to\":\"<subscription-key-after-subscribing-web-notification>\"}";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
Update 2:
Ok now i found how to fire a sync event in service worker file either from google chrome debugger tool or from javascript. Below is the code, what i have found on google's blog post.
// Register your service worker:
navigator.serviceWorker.register('/sw.js');
// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
return swRegistration.sync.register('myFirstSync');
});
Then listen for the event in /sw.js:
self.addEventListener('sync', function(event) {
if (event.tag == 'myFirstSync') {
event.waitUntil(doSomeStuff());
}
});

A good resource for knowing more about ServiceWorker is MDN (Mozilla Developer Network).
Here is the entry point to the documentation related to ServiceWorker:
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
There you have links and explanations for the install, fetch, sync and push events. And the new ones that will appear like background sync will be documented there too.
Happy reading.

Related

POST from Java or JS to GCM

I know there are many different situations that resemble mine across stackoverflow, but I just couldn't make the connection.
What I am trying to do, is to send a simple push notification to the GCM. I found two links for which I try to POST too. Note both these links work in this PHP script i found.
https://gcm-http.googleapis.com/gcm/send
https://android.googleapis.com/gcm/send
I tried to send push notifications from JS to the GCM, but many people have stated that this can not because of security issues. As of now, when I execute my code in Angular JS, I am getting a 405 error from https://gcm-http.googleapis.com/gcm/send. Status 405 means method not accepted (link for reference http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html).
Here is the code for JS. I have two method that I tried.
Method 1:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//ite
}
};
var jsonCall = {
registration_id: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-AEQtUUWnCVH566xcwib4HinI16W3_g"
};
xmlhttp.open("POST", "https://gcm-http.googleapis.com/gcm/send", true);
xmlhttp.setRequestHeader("Content-type", "application/json");
xmlhttp.setRequestHeader("Authorization", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
xmlhttp.send(jsonCall);
Method 2
var jsonCall = {
registration_id: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-AEQtUUWnCVH566xcwib4HinI16W3_g"
};
$http({
method:'POST',
url: 'https://gcm-http.googleapis.com/gcm/send',
data: jsonCall,
headers: {
'Authorization': 'A1nxxxxxxxxxxxxxxxxxx',
'Content-type': 'application/json' }
})
This is what I have tried in Java. Note that my project was not created as an Android project, but just as a normal Java project. I get a 411 error here, so I think the string I use as JSON is incorrect. Note that I get a 200 if I use GET.
Method 3:
HttpURLConnection connection = null;
try {
//Create connection
String json ="{\"registration_ids\":[\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxx\"]}";
URL url = new URL("https://gcm-http.googleapis.com/gcm/send");
connection = (HttpURLConnection)url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setRequestProperty("Content-Length", "0");
connection.setRequestProperty("Authorization", "key="+"xxxxxxxxxxxxxxxxxxxxxxxxxx");
System.out.println(connection.getResponseCode());
InputStream stream = (InputStream) connection.getInputStream();
InputStreamReader isReader = new InputStreamReader(stream);
//put output stream into a string
BufferedReader br = new BufferedReader(isReader);
String line;
while((line = br.readLine()) != null){
System.out.println(line);
}
OutputStream os = connection.getOutputStream();
os.write(json.getBytes("UTF-8"));
os.flush();
os.close();
} catch(Exception e){
System.out.println(e);
}
If someone can take a look at this, and set me in the correct direction, I would really appreciate it.
UPDATE:
I have gotten rid of that 411 error. I think it was because I never connected in the first place. Now I am getting the correct 200 code, but the push notification does not send. Is my JSON the correct format?
HttpURLConnection connection = null;
try {
//Create connection
String json ="{\"registration_ids\":[\"APA91bGxHWapgmxgyvPceu85ArDMLaFekbTt5RGzy3gv1xtSO09tJbvnaeVLefBqNl_iBrctoZQ2AltSMfrXykq8-AEQtUUWnCVH566xcwib4HinI16W3_g\"]}";
URL url = new URL("https://gcm-http.googleapis.com/gcm/send");
connection = (HttpURLConnection)url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", "key=xxxxxxxxxxxxxxxxxxxxxxx");
connection.connect();
OutputStream os = connection.getOutputStream();
os.write(json.getBytes("UTF-8"));
System.out.println(connection.getResponseCode());
InputStream stream = (InputStream) connection.getInputStream();
InputStreamReader isReader = new InputStreamReader(stream);
//put output stream into a string
BufferedReader br = new BufferedReader(isReader);
String line;
while((line = br.readLine()) != null){
System.out.println(line);
}
os.flush();
os.close();
} catch(Exception e){
System.out.println(e);
}
This has been solved using the Java method. JS keeps on returning those status codes of 400, 401, 411 etc. It turns out the reason Java returned a 200 but my phone did not receive anything was because my JSON was incorrect. Here is the correct JSON value:
String postData = "{ \"registration_ids\": [ \"" + CLIENT_REG_ID + "\" ], " +
"\"delay_while_idle\": true, " +
"\"data\": {\"tickerText\":\"My Ticket\", " +
"\"contentTitle\":\"My Title\", " +
"\"message\": \"Test GCM message from GCMServer-Android\"}}";
This was obtained from another question I posted, where a fellow SO member provided this solution.

Apache Abdera Multipart Request throwing nullpointer Exception(IBM connection API)

I am using Apache abdera to post multipart request to IBM connection 4.0 API. I am getting nullpointer exception from Abdera API. Please let me know what's the root cause.
private void createEntryWithAttachment(){
try {
String activityId = "urn:lsid:ibm.com:oa:662d0dc7-0308-48ee-8291-d730c733d2d1";
String activityIdLocal = activityId.substring(activityId.lastIndexOf(":")+1, activityId.length());
String createEntryLocal = createEntry+activityIdLocal;
Abdera abdera = new Abdera();
AbderaClient client = new AbderaClient(abdera);
AbderaClient.registerTrustManager();
System.out.println("pd --->"+pd);
client.addCookie("poktam2cl.iespc.ibm.com", "PD-S-SESSION-ID", pd, "/", null, true);
RequestOptions requestOptions = client.getDefaultRequestOptions();
requestOptions.setUseChunked(true);
requestOptions.setHeader("Connection", "close");
requestOptions.setHeader("Content-Type", "multipart/related;type=\"application/atom+xml\"");
requestOptions.setContentType("multipart/related;type=\"application/atom+xml\"");
requestOptions.setSlug("Sample.txt");
Credentials credentials = new UsernamePasswordCredentials(username, password);
client.addCredentials(createEntryLocal, AuthScope.ANY_REALM,AuthScope.ANY_SCHEME, credentials);
Entry entry = abdera.getFactory().newEntry();
entry.setTitle("create entry with attachment title ");
entry.setContent("create entry with attachment content");
javax.xml.namespace.QName field = new QName("http://www.ibm.com/xmlns/prod/sn", "field", "snx");
org.apache.abdera.model.Element fieldElement = entry.addExtension(field);
fieldElement.setAttributeValue("type", "file");
fieldElement.setAttributeValue("name", "sampletextfile1");
fieldElement.setAttributeValue("position", "3000");
FileInputStream fis = new FileInputStream(filepath);
requestOptions.setHeader("Content-Length", "35");
entry.addCategory("http://www.ibm.com/xmlns/prod/sn/type","entry", "Entry");
ClientResponse response = client.post(createEntryLocal, entry, fis, "multipart/related;type=\"application/atom+xml\"", requestOptions );
System.out.println("Entry Created with attachment's resp: " + response.getStatus());
if(response.getStatus() == 201){
System.out.println("Entry Created with attachment successfully .....");
printIBMConnectionErrorMessage(response);
}else{
System.out.println("Entry with attachment creation failed");
printIBMConnectionErrorMessage(response);
//System.exit(0);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Output
java.lang.NullPointerException
at org.apache.abdera.protocol.client.util.MultipartRelatedRequestEntity.writeInput(MultipartRelatedRequestEntity.java:74)
at org.apache.abdera.protocol.client.util.MultipartRelatedRequestEntity.writeRequest(MultipartRelatedRequestEntity.java:59)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at org.apache.abdera.protocol.client.AbderaClient.execute(AbderaClient.java:688)
at org.apache.abdera.protocol.client.AbderaClient.post(AbderaClient.java:306)
at JavaAgentEntryWithAttachment.createEntryWithAttachment(JavaAgentEntryWithAttachment.java:157)
at JavaAgentEntryWithAttachment.main(JavaAgentEntryWithAttachment.java:66)
This exception is coming from abdera API, class called MultipartRelatedRequestEntity.java, Line no 74. I have placed line no 74 source code below. So its clear that contentSrc is null & Abdera API not allowing me to set this value. Please let me know what I am missing here.
String contentId = entry.getContentSrc().toString();
I did in two steps:
Send the file
Call to update the data
Each with the good mime type. You can not send the file with XML mime type. And put the length of the file.
It is possible to avoid the nullpointer and do it in one request. I had the same issue and created another issue and managed to find a solution. You can find it here.
It comes down to the following code example where you create a HttpClient Part which can contain a StringPart and a FilePart
final Entry entry = // ... Create your Entry
final RequestOptions options = this.client.getDefaultRequestOptions();
options.setHeader("Content-Type", "multipart/related;type=\"application/atom+xml\"");
StringPart entryPart = new StringPart("entry", entry.toString());
entryPart.setContentType("application/atom+xml");
FilePart filePart = new FilePart("file", new File(resource.getFile()));
RequestEntity request = new MultipartRequestEntity(new Part[] { entryPart, filePart}, this.client.getHttpClientParams());
ClientResponse response = client.post(this.url + this.activityId, request, options);
Hope this will help people in the future if they are using Abdera.

INVALID paypal ipn response however [duplicate]

This question already exists:
PayPal IPN Sandbox response always INVALID
Closed 9 years ago.
I am using sandbox mode. I have a buy now button in sandbox mode linked to my sandbox business account which has ipn enabled with the url to my site. The ipn implementation is exactly the same as the sample code here: https://cms.paypal.com/cms_content/GB/en_GB/files/developer/IPN_ASP_NET_C.txt
I click the button and make a purchase using a sandbox personal account which is successful. it shows up as sent with code 200 in the business accounts ipn history but on the ipn page on my site the response is invalid.
Been at this for days now.. cant figure it out :(
Here's what I'm using for https://ASPSecurityKit.net
private void ProcessPayment(bool test)
{
try
{
string callbackResponse = null;
string content = null;
string callbackUrl = test ? "https://www.sandbox.paypal.com/cgi-bin/webscr"
: "https://www.paypal.com/cgi-bin/webscr";
var req = (HttpWebRequest) WebRequest.Create(callbackUrl);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
content = Encoding.ASCII.GetString(
Request.BinaryRead(HttpContext.Request.ContentLength)
);
content += "&cmd=_notify-validate";
req.ContentLength = content.Length;
using (var streamOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII))
{
streamOut.Write(content);
}
using (var streamIn = new StreamReader(req.GetResponse().GetResponseStream()))
{
callbackResponse = streamIn.ReadToEnd();
}
if (callbackResponse.Equals("VERIFIED", StringComparison.OrdinalIgnoreCase))
{
// Now validate whether gross_amount is ok, receiver_email is your business acount mail id and so on.
}
}
catch (Exception ex)
{
// Logger.Log(ex); // Uncomment this line if you have a logger
}
}
Note: I store all transactions in the database whether varified or invalid. That logic is ASPSecurityKit.net specific hence I have omitted that here.

Is there a notification when ASP.NET Web API completes sending to the client

I'm using Web API to stream large files to clients, but I'd like to log if the download was successful or not. That is, if the server sent the entire content of the file.
Is there some way to get a a callback or event when the HttpResponseMessage completes sending data?
Perhaps something like this:
var stream = GetMyStream();
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
// This doesn't exist, but it illustrates what I'm trying to do.
response.OnComplete(context =>
{
if (context.Success)
Log.Info("File downloaded successfully.");
else
Log.Warn("File download was terminated by client.");
});
EDIT: I've now tested this using a real connection (via fiddler).
I inherited StreamContent and added my own OnComplete action which checks for an exception:
public class StreamContentWithCompletion : StreamContent
{
public StreamContentWithCompletion(Stream stream) : base (stream) { }
public StreamContentWithCompletion(Stream stream, Action<Exception> onComplete) : base(stream)
{
this.OnComplete = onComplete;
}
public Action<Exception> OnComplete { get; set; }
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
var t = base.SerializeToStreamAsync(stream, context);
t.ContinueWith(x =>
{
if (this.OnComplete != null)
{
// The task will be in a faulted state if something went wrong.
// I observed the following exception when I aborted the fiddler session:
// 'System.Web.HttpException (0x800704CD): The remote host closed the connection.'
if (x.IsFaulted)
this.OnComplete(x.Exception.GetBaseException());
else
this.OnComplete(null);
}
}, TaskContinuationOptions.ExecuteSynchronously);
return t;
}
}
Then I use it like so:
var stream = GetMyStream();
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContentWithCompletion(stream, ex =>
{
if (ex == null)
Log.Info("File downloaded successfully.");
else
Log.Warn("File download was terminated by client.");
});
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return response;
I am not sure if there is direct signaling that all is ok, but you can use a trick to find out that the connection is exist just before you end it up, and right after you fully send the file.
For example the Response.IsClientConnected is return true if the client is still connected, so you can check something like:
// send the file, make a flush
Response.Flush();
// and now the file is fully sended check if the client is still connected
if(Response.IsClientConnected)
{
// log that all looks ok until the last byte.
}
else
{
// the client is not connected, so maybe have lost some data
}
// and now close the connection.
Response.End();
if the server sent the entire content of the file
Actually there is nothing to do :)
This might sound very simplistic but you will know if an exception is raised - if you care about server delivering and not client cancelling halfway. IsClientConnected is based on ASP.NET HttpResponse not the WebApi.

Google Checkout HTTP Post with ASP.net

I have 2 pages I created in ASP.net(C#). The first one(called shoppingcart.asp) has a buy it now button. The second one(called processpay.asp) just waits for google checkout to send an HTTP request to it to process the payment. What I would like to do send a post statement to google checkout with a couple of variables that I want passed back to processpay.asp(ie clientid=3&itemid=10), but I don't know how to format the POST HTTP statement or what settings I have to change in google checkout to make it work.
Any ideas would be greatly appreciated.
Google Checkout has sample code and a tutorial on how to integrate it with any .NET application:
Google Checkout API - Google Checkout Sample Code for .NET
Make sure to check the section titled: "Integrating the Sample Code into your Web Application".
However, if you prefer to use a server-side POST, you may want to check the following method which submits an HTTP post and returns the response as a string:
using System.Net;
string HttpPost (string parameters)
{
WebRequest webRequest = WebRequest.Create("http://checkout.google.com/buttons/checkout.gif?merchant_id=1234567890");
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(parameters);
Stream os = null;
try
{
webRequest.ContentLength = bytes.Length;
os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
}
catch (WebException e)
{
// handle e.Message
}
finally
{
if (os != null)
{
os.Close();
}
}
try
{
// get the response
WebResponse webResponse = webRequest.GetResponse();
if (webResponse == null)
{
return null;
}
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
return sr.ReadToEnd().Trim();
}
catch (WebException e)
{
// handle e.Message
}
return null;
}
Parameters need to be passed in the form: name1=value1&name2=value2
The code will likely end up looking something like this:
GCheckout.Checkout.CheckoutShoppingCartRequest oneCheckoutShoppingCartRequest =
GCheckoutButton1.CreateRequest();
oneCheckoutShoppingCartRequest.MerchantPrivateData = "clientid=3";
GCheckout.Checkout.ShoppingCartItem oneShoppingCartItem =
new GCheckout.Checkout.ShoppingCartItem();
oneShoppingCartItem.Name = "YourProductDisplayName";
oneShoppingCartItem.MerchantItemID = "10";
oneCheckoutShoppingCartRequest.AddItem(oneShoppingCartItem);
Yesterday I used http://www.codeproject.com/KB/aspnet/ASP_NETRedirectAndPost.aspx to send the post data and it works fine

Resources