RequestDispatcher.forward() not forwarding when servlet called via Ajax POST - javascript

I have a login page where I authenticate the user via firebase and send the request to a servlet. When I hit the submit button with correct authentications, the firebase authentication works, servlet get called but in browser I see see an error.
First of all, this is my javascript code
function toggleSignIn() {
if (firebase.auth().currentUser) {
alert('existing user');
firebase.auth().signOut();
} else {
var email = document.getElementById('email').value;
var password = document.getElementById('password').value;
if (email.length < 4) {
alert('Please enter an email address.');
return;
}
if (password.length < 4) {
alert('Please enter a password.');
return;
}
firebase.auth().signInWithEmailAndPassword(email, password).then(function (firebaseUser) {
var email = firebase.auth().currentUser.email;
const options = {
method: 'POST',
url: 'LoginValidator',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: `email=${email}`
}
url = 'LoginValidator'
fetch(url, options)
.then(response = > response.json())
.then(data = > console.log(data))
.catch(e = > console.error(e))
}).catch(function (error) {
var errorCode = error.code;
var errorMessage = error.message;
if (errorCode === 'auth/wrong-password') {
alert('Wrong password.');
} else {
alert(errorMessage);
}
console.log(error);
document.getElementById('quickstart-sign-in').disabled = false;
});
}
document.getElementById('quickstart-sign-in').disabled = true;
}
HTML
<div id="login-box" class="col-md-12">
<div class="form-group">
<input type="text" name="email" id="email" class="form-control login-input" placeholder="username">
</div>
<div class="form-group">
<input class="form-control login-input" type="password" placeholder="Password" id="password" name="password">
<i id="open" class="fa fa-eye fa-2x"></i>
<i id="closed" class="fa fa-eye-slash fa-2x"></i>
</div>
<div class="form-group">
<input type="submit" id="quickstart-sign-in" name="quickstart-sign-in"
class="form-control btn btn-info btn-md login-bt" value="Login" onclick="toggleSignIn()">
</div>
<div class="form-group text-center forgot">
Forgot username / password?
</div>
</div>
Below is my servlet
LoginValidator.java
public class LoginValidator extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String email = request.getParameter("email");
System.out.println("Printing email: "+email);
try {
System.out.println("inside try");
User user = new User();
UserRight userRight = new UserRight();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new DateTypeDeserializer());
Gson gson = gsonBuilder.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BaseURLs.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
//Get user
RestEndPointsInterface endPoint = retrofit.create(RestEndPointsInterface.class);
Call<User> call = endPoint.getUserByEmail(email);
user = call.execute().body();
System.out.println(user.getName());
//Get user rights
Call<UserRight> userRightCall = endPoint.getUserRightByID(user.getUserRights().getIduserRight());
userRight = userRightCall.execute().body();
System.out.println(userRight.getUserRight());
if(userRight.getUserRight().equals("admin"))
{
response.getWriter().write("{url:LoadSellPendingApprovals}");
}
else
{
response.getWriter().write("{url:index.html}");
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
The LoginValidator calls LoadSellPendingApprovals, below is its code
public class LoadSellPendingApprovals extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
List<ProductSellAdvertisement> categoryList = new ArrayList<ProductSellAdvertisement>();
try {
System.out.println("INSIDE LoadSellPendingApprovals");
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new DateTypeDeserializer());
Gson gson = gsonBuilder.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BaseURLs.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
RestEndPointsInterface endPoint = retrofit.create(RestEndPointsInterface.class);
Call<List<ProductSellAdvertisement>> call = endPoint.getAllPendingApprovals();
categoryList = call.execute().body();
for (int i = 0; i < categoryList.size(); i++) {
System.out.println(categoryList.get(i).getProduct().getProductName());
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally {
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/WEB-INF/jsp/product-sell-pending-approvals.jsp");
request.setAttribute("approvalList", categoryList);
requestDispatcher.forward(request, response);
}
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
This is the error I get
SyntaxError: Unexpected token < in JSON at position 0
at (index):71
The line being pointed in my javascript code is this - .then(response => response.json())
The expected behavior is this
User enter credentials
Authenticate the credentials with firebase javascript api
If credentials are correct send them to the LoginValidator servlet where it will further check user`s authenticity.
Then the LoginValidator send the request to LoadSellPendingApprovals where it will execute the following code
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/WEB-INF/jsp/product-sell-pending-approvals.jsp");
request.setAttribute("approvalList", categoryList);
requestDispatcher.forward(request, response);
In addition to the error I get, I never get forwarded to the JSP page as well. How can I fix this problem?
I am coming from java and mobile background, have no much clue on Javascript technology. Therefor appreciate detailed clear answers.

Your error indicates that the result "body" does not contain JSON but HTML:
Unexpected token < in JSON at position 0
JSON would look like this:
{ key: value }
HTML looks like this:
<html>....</html>
As the error states, the first < (position 0) is the "unexpected token". What ever is reading the body was expecting a {.
One reason for this might be that the request you are sending is redirected to a login page and therefore you get HTML instead of the expected JSON. Or you get an error page which you are trying to pass to your JSON parser.
Unfortunately, with this little information it is hard to tell. You should debug your code and check the response you are getting.

Related

Why is my controller config not allowing a cross-origin call?

I get this error message in my Browser Console, even though I think everything should be working. I´m just starting out with all of this, so I would be very gratefull if someone could help me out here.
Error: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/api/file/upload/. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
This is my Post-Method in the Controller:
#CrossOrigin(origins = "http://localhost:4200", maxAge = 3600, allowCredentials="true")
#PostMapping("/upload/")
public ResponseEntity<Object> uploadBild(#RequestParam("file") MultipartFile file,
#AuthenticationPrincipal User user,
HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
System.out.println("File received Upload: " + file);
String[] allowedTypes = {"image/jpeg", "image/jpg", "image/png"};
if (!Arrays.asList(allowedTypes).contains(file.getContentType())) {
Map<String, String> responseBody = new HashMap<>();
responseBody.put("error", "Invalid file type. Only jpeg and png files are allowed");
return new ResponseEntity<>(responseBody, HttpStatus.BAD_REQUEST);
}
PictureDTO pictureDTO = new PictureDTO();
pictureDTO.setTitle(file.getOriginalFilename());
Picture picture = pictureService.save(pictureDTO, user);
if (uploadService.saveFile(file, picture.getId())){
Map<String, String> response1 = new HashMap<>();
response1.put("message", "File uploaded successfully");
return new ResponseEntity<>(response1, HttpStatus.OK);
}
else {
Map<String, String> response2 = new HashMap<>();
response2.put("message", "File upload failed");
return new ResponseEntity<>(response2, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
These are my application.properties:
spring.data.mongodb.uri=mongodb://user1:pass1#localhost:27017/?authSource=db1&replicaSet=rs1
spring.data.mongodb.database=db1
com.example.demo.accessTokenExpirationMinutes=5
com.example.demo.refreshTokenExpirationDays=30
accessTokenSecret=12345
refreshTokenSecret=54321
spring.web.cors.enabled=true
spring.web.cors.allow-origin=http://localhost:4200
spring.web.cors.allow-credentials=true
This is my WebSecurityConfiguration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(accessTokenEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(accessTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
And this is my frontend API Call:
uploadFile(file: File) {
const formData = new FormData();
formData.append('file', file);
this.http.post('http://localhost:8080/api/file/upload/', formData,{headers: {"Content-Type":"multipart/form-data"}}).subscribe(response => {
console.log(response);
// this.watermarkImage(file, "COPYRIGHT")
});
}
I hope this is enough information. Thank you very much! Best regards!

Getting Firebase Functions Internal Error

I am trying to implement Razorpay Payment Integration with Firebase Cloud Functions API in Android. Every is working fine but when verifying the payment on the server Firebase Functions Throw an Internal Error as FirebaseFunctionsEceptions.InternalError.
This is my server side code
exports.confirmPayment = functions.https.onCall((data, context) => {
if (context.auth) {
const amount = data.amount;
const text = data.razorpay_order_id + "|" + data.razorpay_payment_id;
var signature = crypto
.createHmac("sha256", key_secret)
.update(text)
.digest("hex");
if (signature === data.razorpay_signature) {
console.log("PAYMENT SUCCESSFUL");
return { text: "PAYMENT_SUCCESSFUL" };
} else {
throw new functions.https.HttpsError('Invalid Pack Bought', 'Your payment was unsuccessful due to invalid pack purchasing!')
}
}else{
throw new functions.https.HttpsError('Unauthenticated User', 'Unable to confirm Payment!')
}
});
And my Android Studio Java Code is
When Payment Is Successful Razorpay's onPaymentSuccess is thrown and after the payment I have to verify if the payment made is authentic and has same amount. which is done by verifyPayment method which is given below
#Override
public void onPaymentSuccess(String s, PaymentData paymentData) {
Toast.makeText(this, "Payment Successful verifying now!", Toast.LENGTH_SHORT).show();
Task<String> results = verifyPayment(paymentData);
results.addOnCompleteListener(new OnCompleteListener<String>() {
#Override
public void onComplete(#NonNull Task<String> task) {
if (task.isSuccessful()) {
Snackbar.make(btnBuy.getRootView(), "Points have been added to your balance!", Snackbar.LENGTH_SHORT).show();
} else {
Toast.makeText(BuyPointsActivity.this, "" + task.getException(), Toast.LENGTH_LONG).show();
}
}
});
}
Payment Verification Method is Called Via This Method
private Task<String> verifyPayment(PaymentData data) {
Map<String, Object> data1 = new HashMap<>();
data1.put("razorpay_payment_id", data.getPaymentId());
data1.put("razorpay_order_id", data.getOrderId());
data1.put("amount", amount);
data1.put("razorpay_signature", data.getSignature());
data1.put("push", true);
return functions
.getHttpsCallable("confirmPayment")
.call(data1)
.continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
// This continuation runs on either success or failure, but if the task
// has failed then getResult() will throw an Exception which will be
// propagated down.
String result = (String) task.getResult().getData();
return result;
}
});
}
This is the Cloud Functions Log
confirmPayment
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","authenticationInfo":{"principalEmail":"mmbestonbest#gmail.com"},"requestMetadata":{"callerIp":"47.30.174.168","callerSuppliedUserAgent":"FirebaseCLI/8.0.1,gzip(gfe),gzip(gfe)","requestAttributes":{"time":"2020-04-05T03:49:42.041Z","auth":{}},"destinationAttributes":{}},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","authorizationInfo":[{"resource":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","permission":"cloudfunctions.functions.update","granted":true,"resourceAttributes":{}}],"resourceName":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","request":{"updateMask":"sourceUploadUrl,name,labels,runtime,httpsTrigger","#type":"type.googleapis.com/google.cloud.functions.v1.UpdateFunctionRequest","function":{"runtime":"nodejs8","name":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","httpsTrigger":{},"labels":{"deployment-callable":"true","deployment-tool":"cli-firebase"},"sourceUploadUrl":"https://storage.googleapis.com/gcf-upload-us-central1-2535687d-781c-43d3-8bb1-6cdc1434531f/0cdb81e8-551c-4de7-83c0-8fe50f5a97bb.zip?GoogleAccessId=service-615941328944#gcf-admin-robot.iam.gserviceaccount.com&Expires=1586060376&Signature=rF3FqDJFIbAXSLK8DiemM6X%2BfTvMhv6RMpSvFCaHFjSfQ1kEf%2B5jV92LColV1k0szPt98HsExV2u2HGHRBSobobloyY8oAyh94WYHQTkVQZfhRGCOTvSliuhIhE98kRLVLOEPOjkyhNlz1v9kz48z1tq%2BRYyFB224joiU6qx4Qa58a08QZ3a1Ty4yQAuYedz2lgj3auKoJj10MzGf9T9YW3ffvN9vy4fF1z10erVaNMspgrZoU43NnJGWt%2B185ZRT9Gx%2B6mfxYinkXlfeVj3b8WOKwcYGbtN1FnFaUf8wGX3fAb%2B6FRB2n5ATIchyNHnr1F7E6sbdpmG5cCDZE1kbQ%3D%3D"}},"resourceLocation":{"currentLocations":["us-central1"]}}
9:20:10.642 AM
confirmPayment
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","status":{},"authenticationInfo":{"principalEmail":"mmbestonbest#gmail.com"},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","resourceName":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment"}
9:21:23.540 AM
confirmPayment
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","authenticationInfo":{"principalEmail":"mmbestonbest#gmail.com"},"requestMetadata":{"callerIp":"47.30.174.168","callerSuppliedUserAgent":"FirebaseCLI/8.0.1,gzip(gfe),gzip(gfe)","requestAttributes":{"time":"2020-04-05T03:51:23.614Z","auth":{}},"destinationAttributes":{}},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","authorizationInfo":[{"resource":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","permission":"cloudfunctions.functions.update","granted":true,"resourceAttributes":{}}],"resourceName":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","request":{"updateMask":"sourceUploadUrl,name,labels,runtime,httpsTrigger","#type":"type.googleapis.com/google.cloud.functions.v1.UpdateFunctionRequest","function":{"sourceUploadUrl":"https://storage.googleapis.com/gcf-upload-us-central1-2535687d-781c-43d3-8bb1-6cdc1434531f/87426444-4523-4584-a501-e219ac62e36e.zip?GoogleAccessId=service-615941328944#gcf-admin-robot.iam.gserviceaccount.com&Expires=1586060478&Signature=g2AJztAxLbvci2q7MDms1K7%2B466Z2RM6ALQmeBdH%2By7AA3hMAkdKSI7B3FzY8g1m%2BBuMlO8fkCWBSXcgHauxsOni%2FNW1LD7MZ%2FSUSkZ4npE%2FyVNRy0aitEzVSo6GaPmV9415KoFADyXHAxNakuD8JPZ4wl7qn%2FdcmQ8cZRJ%2BX%2BZ7w2xRw6BmG%2Fbnnmy8DCZe%2F%2Fw%2BIBhM4bpSOO8Ne8nMDa7qAfMzMXHHU8PDuIuIqdOmdIG0xF0itGsw3bhvAc530xWcJY%2F%2B7u%2FUjaszVikTV9igU33nUsqA5%2FzuNLmXrR9B42gn1ncCiwjnx8rlrcETmKkMrD6%2FABM5nYEQ%2Fvy%2BRw%3D%3D","runtime":"nodejs8","name":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","httpsTrigger":{},"labels":{"deployment-tool":"cli-firebase","deployment-callable":"true"}}},"resourceLocation":{"currentLocations":["us-central1"]}}
9:21:56.574 AM
confirmPayment
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","status":{},"authenticationInfo":{"principalEmail":"mmbestonbest#gmail.com"},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","resourceName":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment"}
11:45:07.349 AM
confirmPayment
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","authenticationInfo":{"principalEmail":"mmbestonbest#gmail.com"},"requestMetadata":{"callerIp":"47.30.162.219","callerSuppliedUserAgent":"FirebaseCLI/8.0.1,gzip(gfe),gzip(gfe)","requestAttributes":{"time":"2020-04-05T06:15:07.712Z","auth":{}},"destinationAttributes":{}},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","authorizationInfo":[{"resource":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","permission":"cloudfunctions.functions.update","granted":true,"resourceAttributes":{}}],"resourceName":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","request":{"updateMask":"sourceUploadUrl,name,labels,runtime,httpsTrigger","#type":"type.googleapis.com/google.cloud.functions.v1.UpdateFunctionRequest","function":{"runtime":"nodejs8","name":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment","httpsTrigger":{},"labels":{"deployment-callable":"true","deployment-tool":"cli-firebase"},"sourceUploadUrl":"https://storage.googleapis.com/gcf-upload-us-central1-2535687d-781c-43d3-8bb1-6cdc1434531f/82b41c31-8b5c-4cd4-857c-301b4f554dd5.zip?GoogleAccessId=service-615941328944#gcf-admin-robot.iam.gserviceaccount.com&Expires=1586069101&Signature=FNLT8XrMwerp00RaqJXMPj6qk7Ztawx0NSAYJIWnWsMy0xdvB0bgqUrYx0dUYGx38r1c6xtyN7mSqFEXEN4IDOkDqWCRFDibiABDmTG9J60F2822bCeReGyYvmTJGVA%2BvBELdtvoiSBaVFHHYQfQdCKGKObboW2950zEeuq52pk30M3doDCUoXuGQUDSpQrZnlXLabH6JjvPDDj6VYcF42HnUmnesd43yErky6ZiW2qo6F4nGAj9hwEDAKFJHX%2FoW1HLDdMjQ2EI0t9%2FPRBi6fvtNjLqbAtE7xjQSwvDlyU1uMFAqwVC5RxKeTGM195E6RbKlSY6YsEzp4rAWltU%2Fw%3D%3D"}},"resourceLocation":{"currentLocations":["us-central1"]}}
11:45:32.142 AM
confirmPayment
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","status":{},"authenticationInfo":{"principalEmail":"mmbestonbest#gmail.com"},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","resourceName":"projects/beingfit-6c699/locations/us-central1/functions/confirmPayment"}
Logs are subject to Cloud Logging's

How to throw HttpsError in onCall() function and catch on android client

I'm trying to create a stripe charge using a cloud function, and I only receive INTERNAL exception on the client. Where and how should the HttpsError be thrown to be caught by an android client.
I followed the cloud functions documentation found here, but when I came to the error handling section I only retrieve INTERNAL.
Code I have tried:
exports.createCharge = functions.https.onCall((data, context) => {
var amount = data.amount * 100
var token = data.token
var info = {
amount: amount,
currency: 'usd',
description: 'Concession Charge',
source: token
}
stripe.charges.create(info, (err, charge)=>{
if(err){
throw new functions.https.HttpsError(err.type, err.message)
}else{
return charge
}
})
})
Since stripe.charges.create(info); returns a promise i've also tried:
return stripe.charges.create(info).then((charge) => {
return charge;
}).catch((error) =>{
throw new functions.https.HttpsError(err.type, err.message)
})
My client-side code is basically the same as the documentation.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//......
confirmBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
submitPayment("tok_chargeDeclinedInsufficientFunds", 8.50)
.addOnCompleteListener(paymentCallback);
}
}
//......
}
//Function Call
private Task<String> submitPayment(String token, double amount) {
Log.d(TAG, "Submitting Payment of: $" + amount);
// Create the arguments to the callable function.
Map<String, Object> data = new HashMap<>();
data.put("token", token);
data.put("amount", amount);
return mFunctions
.getHttpsCallable("createCharge")
.call(data)
.continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
String result = (String) task.getResult().getData();
return result;
}
});
}
//Function Complete callback
OnCompleteListener<String> paymentCallback = new OnCompleteListener<String(){
#Override
public void onComplete(#NonNull Task<String> task){
if (!task.isSuccessful()){
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
FirebaseFunctionsException.Code code = ffe.getCode();
Object details = ffe.getDetails(); //DEBUG BREAKPOINT HERE
}
}
}
}
};
I expect to have the Exception in my paymentCallback that reads the specific details of why it failed, but instead I only get an Internal error everytime.
According to the documentation:
To ensure the client gets useful error details, return errors from a callable by throwing (or returning a Promise rejected with) an instance of functions.https.HttpsError.
So I would try returning a rejected promise created with Promise.reject(...) rather than throwing an exception out of the catch callback.

Why is this Cloud Function called more than once with an Android HTTP request trigger?

I have a function in an Android app which sends a POST request to an HTTP triggered Cloud Function. Whenever I click the button once to send the message, Firebase registers the event twice on the Firebase console. My application is built in such a way that the button to send a message disappears after the first click, so I'm not accidentally double clicking the button, and when I step through the debugger, the function to send the POST request is only called once. Can you guys help me? I don't know much about Firebase and can't find good documentation or other questions like this.
Here's the method which sends a message to my FCM cloud function:
public void sendPushToSingleInstance(final Context activity, final String message, final String myId, final String theirId) {
final String url = URL_TO_CLOUD_FUNCTION;
StringRequest myReq = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(activity, "Success", Toast.LENGTH_SHORT).show();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (error.networkResponse != null)
Toast.makeText(activity, String.valueOf(error.networkResponse.statusCode), Toast.LENGTH_SHORT).show();
else
Toast.makeText(activity, "some error", Toast.LENGTH_SHORT).show();
}
}) {
#Override
public byte[] getBody() throws com.android.volley.AuthFailureError {
Map<String, String> rawParameters = new Hashtable<String, String>();
//not used
return new JSONObject(rawParameters).toString().getBytes();
};
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("from", myId);
headers.put("message", message);
headers.put("sendingTo", theirId);
return headers;
}
};
Volley.newRequestQueue(activity).add(myReq);
}
My JavaScript takes the HTTP request, cuts it up and send the message to a topic which contains the other user's id (I did mean to do this verses sending to a specific device).
Here's the JavaScript for my Cloud Function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendMessage = functions.https.onRequest((request, response) => {
var topicId = request.get('sendingTo');
var color = request.get('color');
var from = request.get('from')
console.log('tried to push notification');
const payload = {
notification: {
title: from,
body: color,
sound: "default"
},
};
const options = {
priority: "high",
timeToLive: 60 * 60 * 24
};
admin.messaging().sendToTopic(topicId, payload, options);
});
Finally, here are the logs:
firebase console logs
Which say that the function was called twice.
I've tried many links for answers such as the standard,
https://firebase.google.com/docs/functions/http-events
and many StackOverflow posts. I haven't seen anyone else with the same problem.
From #mohamadrabee, "this from the documentation 'Always end an HTTP function with send(), redirect(), or end(). Otherwise, your function might to continue to run and be forcibly terminated by the system.' see firebase.google.com/docs/functions/http-events "
I added:
response.end();
after:
admin.messaging().sendToTopic(topicId, payload, options);
EDIT: After inserting this code, I still get the problem roughly 7% of the time. I had to change response.end(); to:
if (response.status(200)) {
response.status(200).end();
} else {
response.end();
}
I haven't had any problems since.

HttpRequestHandler : Sending a pdf file in response

I want server a pdf file instead of mp3 file please help
private HttpRequestHandler mRequestHandler = new HttpRequestHandler()
{
#Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context)
throws HttpException, IOException
{
try{
File file = new File("/mnt/sdcard/Music/song.mp3");
FileEntity body = new FileEntity(file, "audio/mpeg");
response.setHeader("Content-Type", "application/force-download");
response.setHeader("Content-Disposition","attachment; filename=song.mp3");
response.setEntity(body);
}catch(Exception e)
{
e.printStackTrace();
}
}
};
Change the content type to application/pdf
#Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context)
throws HttpException, IOException
{
try{
File file = new File("/my/path/file.pdf");
FileEntity body = new FileEntity(file, "application/pdf");
response.setHeader("Content-Type", "application/force-download");
response.setHeader("Content-Disposition","attachment; filename=file.pdf");
response.setEntity(body);
}catch(Exception e)
{
e.printStackTrace();
}
}
};
you can check mime types here

Categories

Resources