Laravel API Rest doesn't work in device Android - android

I have an app in IONIC and in browser the call to API works but when I run on android device it shows this error:
HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "http://192.168.1.***:8080/api/auth/login", ok: false, …}
error: ProgressEvent {isTrusted: true, lengthComputable: false, loaded: 0, total: 0, type: "error", …}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, headers: Map(0)}
message: "Http failure response for http://192.168.1.***:8080/api/auth/login: 0 Unknown Error"
name: "HttpErrorResponse"
ok: false
status: 0
statusText: "Unknown Error"
url: "http://192.168.1.***:8080/api/auth/login"
__proto__: HttpResponseBase
In IONIC I send like API_URL = 'http://192.168.1.***:8080/api/'; to use HttpClient, and in Laravel I run php artisan serve --host 192.168.1.*** --port 8080
Please, someone knows what I should do to work?

The issue is related to CORS. You don't have to do anything to your IONIC app. You can enable CORS request by adding required headers for that you can create your own middleware in Laravel to handle cors, A sample middleware would be:
namespace App\Http\Middleware;
use Closure;
class Cors
{
public function handle($request, Closure $next)
{
return $next($request)->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', '*');
}
}
Then use it, by editing app\Http\Kernel.php
protected $middlewareGroups = [
'web' => [
// middleware for your web routes
],
'api' => [
'throttle:60,1',
'bindings',
'cors',
],
]
protected $routeMiddleware = [
// other middleware code
'cors' => \EuroKids\Http\Middleware\Cors::class,
]
You can customize the above middleware as required.
However, if you don't want to do create your own middleware you can use this library:
https://github.com/barryvdh/laravel-cors

Related

Why does my API work correctly (specifically, parameters) with Postman, but not with React Native?

My API is a very basic Python script with Sanic, I have a SSL certificate from letsencrypt, and the server is running on an AWS Lightsail instance. Both Postman and my React Native application are running in a separate Windows 11 machine.
Here's the relevant API code:
from os import abort
from sanic import Sanic
from sanic.response import json
app = Sanic(name="APIbuilding")
ssl = {
"cert": "/home/ec2-user/keys/fullchain.pem",
"key": "/home/ec2-user/keys/privkey.pem",
}
#app.route('/loginRequest')
async def confirm(request):
email = str(request.args.get("email"))
password = str(request.args.get("password"))
return json({'hello': 'world'}, headers={"Access-Control-Allow-Origin": "*","Access-Control-Allow-Methods": "*"})
if __name__ == '__main__':
app.run(host='123.456.789.875', port=8443, ssl=ssl)
My request in Postman works:
https://www.example.com/loginRequest/?email=example#mail.com&password=password
Returns
{
"hello": "world"
}
And I can see the correct logs in my server:
[2022-10-18 16:22:07 +0000] - (sanic.access)[INFO][123.123.123.123:49339]: POST https://www.example.com/loginRequest/?email=example#mail.com&password=password 200 30
I can see the parameters sent, and I can read the values in the server. However, I have not been able to replicate this using React Native (or Android Studio, for that matter).
My React Native code is as follows:
import React from 'react';
import { Button, View } from 'react-native';
const App = () => {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Button
onPress={() =>
fetch('https://www.example.com/loginRequest/', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: {
"email": "example#mail.com",
"password": "password"
}
})
}
title="POST to API"
/>
</View>
);
}
export default App;
On the Android Emulator, I see the correct view, which is a plain button with the text "POST TO API". When I click on it, I see activity in the server. There is a connection. However, it doesn't send the body of the request. The log looks like this:
[2022-10-18 16:31:52 +0000] - (sanic.access)[INFO][123.123.123.123:49339]: POST https://www.example.com/loginRequest/ 200 30
Note that there are no parameters in the log this time. Also, I get the same result when using JSON stringify to build the body of the fetch request.
API expects credentials as query parameters, so something like this would work:
fetch(`https://www.example.com/loginRequest/?email=${email}&password=${password}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}
On your backend side, you take params from the URL as far as I understand (https://sanic.dev/en/guide/basics/request.html#parameters). On React Native side you pass another body params. You need to pass your params as a part of the URL or change your backend handler.

Unable to send ajax get requests with Meteor on Android *only*

I’ve got several Meteor apps that heavily rely on ajax get requests. At some point, one of these apps stopped being able to send ajax get requests, on recent versions of Android, only.
The same app works in the browser, on iOS, and on older versions of Android. (Or rather, on a Fire tablet.) So, I take this to mean this is not a CORS issue.
Other apps, using the same code, are not affected, on any platform.
It appears to me that Android is blocking the requests, and I don’t understand how to make this work.
Also, I've not found a device with recent version of Android where this does work, meaning it's not just my phone.
This is an example request:
$.ajax({
type: "GET",
traditional: true,
url: url,
contentType: 'application/json; charset=utf-8',
dataType: "json",
data: {},
success: function (result) {
...
},
error: function (xhr) {
var propValue;
for(var propName in xhr) {
propValue = xhr[propName]
$("#log").prepend(propName + ": " + propValue + "<br />");
}
}
});
This is the output:
statusText: error
status: 0
responseText:
error: function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){p.each(n,(function(n,r){p.isFunction®?e.unique&&l.has®||o.push®:r&&r.length&&“string”!==p.type®&&t®}))}(arguments),n&&!t&&u()),this}
success: function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){p.each(n,(function(n,r){p.isFunction®?e.unique&&l.has®||o.push®:r&&r.length&&“string”!==p.type®&&t®}))}(arguments),n&&!t&&u()),this}
complete: function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){p.each(n,(function(n,r){p.isFunction®?e.unique&&l.has®||o.push®:r&&r.length&&“string”!==p.type®&&t®}))}(arguments),n&&!t&&u()),this}
progress: function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){p.each(n,(function(n,r){p.isFunction®?e.unique&&l.has®||o.push®:r&&r.length&&“string”!==p.type®&&t®}))}(arguments),n&&!t&&u()),this}
fail: function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){p.each(n,(function(n,r){p.isFunction®?e.unique&&l.has®||o.push®:r&&r.length&&“string”!==p.type®&&t®}))}(arguments),n&&!t&&u()),this}
done: function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){p.each(n,(function(n,r){p.isFunction®?e.unique&&l.has®||o.push®:r&&r.length&&“string”!==p.type®&&t®}))}(arguments),n&&!t&&u()),this}
pipe: function(){var e=arguments; return p.Deferred((function(n){p.each(t,(function(t,o){var a=p.isFunction(e[t])&&e[t]; i[o[1]]((function(){var e=a&&a.apply(this,arguments); e&&p.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):no[0]+“With”}))})),e=null})).promise()} promise: function(e){return null!=e?p.extend(e,r):r}
then: function(){var e=arguments; return p.Deferred((function(n){p.each(t,(function(t,o){var a=p.isFunction(e[t])&&e[t]; i[o[1]]((function(){var e=a&&a.apply(this,arguments); e&&p.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):no[0]+“With”}))})),e=null})).promise()}
always: function(){return i.done(arguments).fail(arguments),this}
state: function(){return n}
abort: function(e){var t=e||w; return l&&l.abort(t),C(0,t),this}
statusCode: function(e){var t; if(e)if(b<2)for(t in e)v[t]=[v[t],e[t]]; else T.always(e[T.status]); return this}
overrideMimeType: function(e){return b||(f.mimeType=e),this}
setRequestHeader: function(e,t){var n=e.toLowerCase(); return b||(e=x[n]=x[n]||e,y[e]=t),this}
getAllResponseHeaders: function(){return 2===b?a:null}
getResponseHeader: function(e){var t; if(2===b){if(!c)for(c={}; t=Pt.exec(a); )c[t[1].toLowerCase()]=t[2]; t=c[e.toLowerCase()]}return null==t?null:t}
readyState: 0
Any insight would be greatly appreciated.
Check your SSL on backend.
Since Android 9, your api end point must :
Use HTTPS
Not be self-signed
Use public certificate authority
only

Ajax request not sending on android cordova

Ajax request not sending on android studio with cordova. I tried a simple request to google but it does not work either.
What i already tried :
- Change minSdk to 23
- Add cordova whitelist plugin and permissions for https and http in config.xml
- add android:usesCleartextTraffic="true" in AndroidManifest
- i have nothing in my network profiler but ajax return a timeout error
- Outside my app, my request work
Code
$.ajax({
type: "POST",
url: OAUTH2_URL,
cache : false,
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', make_base_auth($("#login").val(), $("#pwd").val()));
},
dataType: 'json',
contentType: 'application/json; charset=UTF-8',
data: json,
timeout: 5000,
success: function (data) {
etape3(data);
},
error: function (xhr, ajaxOptions, thrownError){
SpinnerPlugin.activityStop();
navigator.notification.confirm(
'login or password incorrect.', // message
null, // callback
'Error', // title
['Ok'] // buttonName
);
}
})
I don't know what else to do
Thanks !

React-native / AWS API Gateway android issue

I am trying to use react-native with aws api gateway. Same code ( pure JS ) works great on ios but on android it fails with 403 error.
var signedRequest={
"headers": {
"Content-Type": "application/json",
"Accept": "application/json",
"x-amz-date": "20170918T134411Z",
"Authorization": "AWS4-HMAC-SHA256 Credential=ASIAIBC7RQ7MFUIRO7QQ/20170918/ap-northeast-1/execute-api/aws4_request, SignedHeaders=accept;content-type;host;x-amz-date, Signature=9fb6d4d4820024097f25aaa70648fxxx7a54a2db1a67d173189693dc073d0a0bac8",
"x-amz-security-token": "AgoGb3JpZ2luEKn////////xxxG1iKJBHjjvZH0DxcSqE889Wb3Mv+8PwMqrRe/O5dFFmP+9bQj+fSwVIUvmBplKkQB62x/xTelGHoCEOPXpBWLjT2OAUaBXOti7UZyfyMNgg56/Z58yxk4o2/37xPLbhXfODaL8kydFV8IaPJjdbJIX+a0kXycPLBnVIBdukUp9cMVD27mWN41u3w0VP5J8YiMPzrDnwKtb0U37naoIaknMBqNBDkMGQyHal/TBJ3wjJvJWVntrJvex0QKD8rDLHjaoiIYjBd+a04m2pKsBQJ9WQl02TTCPgRp0bb1oARF2hz0Xpi45Ba6a6E9SAL07UcRShTwX6rmxi0dZ38mkSbBMjI45Xg8r/VaRZx6/OyCq3u+nq4bgLCOMKqb/80F"
},
"data": "{\"data\":{\"func\":\"checkIfFacebookSignupComplete\",\"data\":{}}}",
"method": "POST",
"url": "https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/user/user"
}
var apiResponse=await fetch(signedRequest.url, {
method: signedRequest.method,
body: signedRequest.data,
headers: signedRequest.headers,
})
console.log("Got api response : ", apiResponse)
On iOS it receives a http response 200. However, on android it fails with:
"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
The Canonical String for this request should have been
'POST
/dev/user/user
accept:application/json
content-type:application/json; charset=utf-8
host:uihw7hnkn7.execute-api.ap-northeast-1.amazonaws.com
x-amz-date:20170918T134411Z
accept;content-type;host;x-amz-date
6b83b80f2875c2425c28b258886ad98603fd802095e35303a3c2a72528374fb5'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20170918T134411Z
20170918/ap-northeast-1/execute-api/aws4_request
008853cdfba53255257d9169e1a9c05500d01299da9efd4695ac8c66cb31e5e7'
"
I have tried axios as well . and same result. ( ios works fine, android fails ) I am using react-native 0.42.3.
Anyone got any idea what might be the issue?
After digging around a lot it appears the issue is related to as described here: https://github.com/facebook/react-native/issues/14445 . android okHttp library ( inernally used by react-native ) added charset=utf=8 to the request. So the solution is to calculate sig4 value with header like this:
var signedRequest={
"headers": {
"Content-Type": "pplication/json; charset=utf-8",
"Accept": "application/json",
"x-amz-date": "20170918T134411Z",
"Authorization": "Calculated sig4 auth",
"x-amz-security-token": "AgoGb3JpZ2luEKn////////xxxG1iKJBHjjvZH0DxcSqE889Wb3Mv+8PwMqrRe/O5dFFmP+9bQj+fSwVIUvmBplKkQB62x/xTelGHoCEOPXpBWLjT2OAUaBXOti7UZyfyMNgg56/Z58yxk4o2/37xPLbhXfODaL8kydFV8IaPJjdbJIX+a0kXycPLBnVIBdukUp9cMVD27mWN41u3w0VP5J8YiMPzrDnwKtb0U37naoIaknMBqNBDkMGQyHal/TBJ3wjJvJWVntrJvex0QKD8rDLHjaoiIYjBd+a04m2pKsBQJ9WQl02TTCPgRp0bb1oARF2hz0Xpi45Ba6a6E9SAL07UcRShTwX6rmxi0dZ38mkSbBMjI45Xg8r/VaRZx6/OyCq3u+nq4bgLCOMKqb/80F"
},
"data": "{\"data\":{\"func\":\"checkIfFacebookSignupComplete\",\"data\":{}}}",
"method": "POST",
"url": "https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/user/user"
}
The new AWS Amplify library (https://github.com/aws/aws-amplify) on the official AWS repo has support for automatic signing to API Gateway. This is part of the API module: https://github.com/aws/aws-amplify/blob/master/media/api_guide.md
You would first install the React Native npm module:
npm install aws-amplify-react-native
Then link the project: https://github.com/aws/aws-amplify/blob/master/media/quick_start.md#react-native-development
After that you can configure APIs:
import Amplify, { API } from 'aws-amplify';
Amplify.configure(
Auth: {
identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX-1234-abcd-1234567890ab', //REQUIRED - Amazon Cognito Identity Pool ID
region: 'XX-XXXX-X', // REQUIRED - Amazon Cognito Region
userPoolId: 'XX-XXXX-X_abcd1234', //OPTIONAL - Amazon Cognito User Pool ID
userPoolWebClientId: 'XX-XXXX-X_abcd1234', //OPTIONAL - Amazon Cognito Web Client ID
},
API: {
endpoints: [
{
name: "ApiName1",
endpoint: "https://1234567890-abcdefgh.amazonaws.com"
},
{
name: "ApiName2",
endpoint: "https://1234567890-abcdefghijkl.amazonaws.com"
}
]
}
});
Following that your API Gateway requests are signed using the user's credentials:
let apiName = 'MyApiName';
let path = '/path';
let myInit = { // OPTIONAL
headers: {} // OPTIONAL
}
API.get(apiName, path, myInit).then(response => {
// Add your code here
});
I was fighting with the same issue. GET worked on both platforms, but POST only on iOS. Setting Content-Type to "application/json; charset=utf-8" before signing the request with sigV4Client fixed it for me.
const path = 'https://your-aws-endpoint.com';
const method = 'POST';
const queryParams = {};
const body = {};
const headers = {
'Content-Type' = 'application/json; charset=utf-8';
};
const client = sigV4Client.newClient({
accessKey: ACCESS_KEY,
secretKey: SECRET_ACCESS_KEY,
sessionToken: SESSION_TOKEN,
region: REGION,
endpoint: ENDPOINT,
});
const signedRequest = client.signRequest({
method: method,
path: path,
headers: headers,
queryParams: queryParams,
body: body
});
fetch(signedRequest.url, {
method: method,
headers: signedRequest.headers,
body: JSON.stringify(body)
}).then((results) => {
...
});

cordova angularjs mobile app failing to retrieve data from success response callback (network call)?

I have working angular js application from the browser, through which able to retrieve successfully data from the $http network call,
but the same appliction when i have done mobile package with cordova (either android/ios in both cases), unable to retrieve the data from success response callback with the network call.
configurations are listed below:
corodva 6.4.0 version,
android marshmallow version,
xcode have 8.2.1 version & simulator of 10.2 version,
$http({
method : 'POST',
withCredentials : true,
headers : {
'X-IBM-Client-ID' : "xxx",
'X-IBM-Client-Secret' : "xxx",
'Content-Type' : 'application/json'
},
data : {},
url : "xxx",
}).success(function(data) {
console.log("in successful call back json data:"+JSON.stringify(data)+" data:"+data);
}).error(function(data){
console.log("error due to "+ data);
});
let me know if any suggestions how to proceed on this.
thanks & regards,
vasu.
remove comma after url: "xxx" and use .then instead of success and error
$http({
method : 'POST',
withCredentials : true,
headers : {
'X-IBM-Client-ID' : "xxx",
'X-IBM-Client-Secret' : "xxx",
'Content-Type' : 'application/json'
},
data : {},
url : "xxx"
}).then(function(data) {
console.log("in successful call back json data:"+JSON.stringify(data)+" data:"+data);
}, function(error){
console.log("error due to "+ error);
});

Categories

Resources