How can I log an HTTP POST response in React Native app? - post

I have a simple React Native app with a button. On press, it calls the following function which makes a POST request.
I have tested in POSTMAN and the request works. However, I want to test my app and I'm unable to log the response or any errors. Only the console.log statements for 'here' and 'done' are being printed (I see them in Chrome using remote debugger).
It seems like the fetch function is just being ignored, no warning/errors/logs.
What am I doing wrong here? Or what's the best way to make sure the Request is working?
_onPressButton() {
console.log('here');
fetch('http://passport.local/oauth/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
client_id: '2',
client_secret: 'value',
grant_type: 'password',
username: 'value',
password: 'value',
})
})
.then((response) => response.json())
.then((responseJson) => {
console.warn(xhr.responseText);
console.log(responseJson);
return responseJson;
})
.catch((error) => {
console.error(error);
});
console.log('done');
}

Seems like the virtual host wasn't being resolved. I used ngrok to tunnel the address "passport.local" into an ngrok URL and it worked.

Related

No Cookies with Rails API, CORS and Next getInitialProps

I have a Rails API only backend with rack-cors installed at port 3000.
My NextJS is running on port 5000.
My goal is to consume a cookie set by the server within my NextJS app. It contains a JWT token which holds an email and roles, which will be decoded and used for Authorization.
With Postman I can see the Cookie.
I have set my Cookie in Rails with httpOnly, but I can't see it my Chrome-dev-tools.
When I set a httpOnly cookie with NextJS, it's present.
I can see it in the DevTools "response" when POST to Rails's /login but not in the Application -> Storage -> Cookies(see images attached).
It seems Chrome does not set the cookie in DevTools "storage", it's always empty. Equally if I use "httpOnly" or not.
Can someone help me to consume the Cookie on NextJS (client side)?
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'localhost:5000', '127.0.0.1:5000'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
expose: ['Per-Page', 'Total', 'Link', 'ETag', 'Set-Cookie']
end
Here I set my cookie in the Rails controller:
response.set_cookie(
"withIP",
{
value: auth_token[:token],
expires: 30.minutes.from_now,
path: "/",
domain: "localhost:5000", # tried to remove domain completly also tried "127.0.0.1" as domain, as well as '.localhost'
secure: Rails.env.production?,
httponly: true # Rails.env.production?
}
)
This is my request in the NextJS app:
return fetch(`${PublicApiUrl}/auth/login.json?${qs.stringify(options)}`,
{ method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
credentials: 'same-origin', // also tried 'credentials' and with 'inline', as well completely removed at all.
})
.then((response) => {
console.log("RESPONSE", response); // 1* see image below
console.log("RESPONSE HEADERS", response.headers); // *2 ALWAYS undefined
console.log("RESPONSE forEeach", response.headers.forEach(console.log)); // ALWAYS undefined
console.log("response.headers.get('set-cookie')", response.headers.get('set-cookie')); // NULL
console.log("document.cookie", document.cookie); // nope
return response.json()
} )
.then((data)=>{
console.log("DATA", data); // returns my authToken
return data;
})
*1 console.log from above
RESPONSE
Response {type: 'cors', url: 'http://localhost:3000/auth/login.json?email=xxxxxxx&password=xxxxxx', redirected: false, status: 200, ok: true, …}
body: (...)
bodyUsed: true
headers: Headers
[[Prototype]]: Headers
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:3000/auth/login.json?email=XXXXXX&password=XXXXXX"
*2 RESPONSE HEADERS (console.log from above)
RESPONSE HEADERS Headers {}[[Prototype]]: Headers

Using Rails, how should I configure my application.rb in order to allow for CORS requests to take place?

I am using Rails as a backend API to support a frontend that is made with VueJS. I want to send a POST request from VueJS when a button is pressed on the website, I have used axios to do this
`
methods: {
// Performs a POST request to the rails endpoint and passes the email and pass as parameters
signup() {
if (this.password === this.password_confirmation) {
this.$http.plain
.post("/signup", {
email: this.email,
password: this.password,
password_confirmation: this.password_confirmation
})
// If successful execute signinSuccesful
.then(response => this.signinSuccesful(response))
// If it doesn't run for whatever reason, execute signupFailed
.catch(error => this.signinFailed(error));
}
},`
This should in theory create a POST request that would be received by the API, I have attempted to catch the request like this: post "signup", controller: :signup, action: :create
However, when I look in the console on chrome I get an error when I first load the site:
`0/signin net::ERR_CONNECTION_REFUSED`
And another error when I click the button to send the POST request:
*
Access to XMLHttpRequest at 'http://localhost:3000/signup' from origin
'http://localhost:8080' has been blocked by CORS policy: Request
header field content-type is not allowed by
Access-Control-Allow-Headers in preflight response.
My 'application.rb' file looks like this:
`module RecordstoreBackend
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0
config.api_only = true
config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :patch, :put, :delete, :post, :options]
end
end`
I think the issue is this file, but I am not sure how to configure it. Thanks for your help.
It seems to me like you're missing the host for that request (on your Vue app). Notice the error says 0/signup which indicates that it's sending the request to http://0/signup that is, in turn, "rejecting" the connection.
I'm not familiar with Vue.js structure, but I'd recommend encapsulating the axios call on a plugin that would use the host from an environment configuration file, so that you can have different hosts for localhost and your production env. Or even just add the host to your environment:
methods: {
// Performs a POST request to the rails endpoint and passes the email and pass as parameters
signup() {
if (this.password === this.password_confirmation) {
this.$http.plain
.post(`${process.env.API_HOST}/signup`, {
email: this.email,
password: this.password,
password_confirmation: this.password_confirmation
})
// If successful execute signinSuccesful
.then(response => this.signinSuccesful(response))
// If it doesn't run for whatever reason, execute signupFailed
.catch(error => this.signinFailed(error));
}
},
Reference: https://cli.vuejs.org/guide/mode-and-env.html#environment-variables
If you want to fix it the way you have it now, simply add your host to the axios call:
methods: {
// Performs a POST request to the rails endpoint and passes the email and pass as parameters
signup() {
if (this.password === this.password_confirmation) {
this.$http.plain
.post("http://localhost:3000/signup", {
email: this.email,
password: this.password,
password_confirmation: this.password_confirmation
})
// If successful execute signinSuccesful
.then(response => this.signinSuccesful(response))
// If it doesn't run for whatever reason, execute signupFailed
.catch(error => this.signinFailed(error));
}
},
About the CORS error, check this: https://stackoverflow.com/a/25727411/715444

Sending cookie in XHR response but it's not getting stored?

I'm trying to pass an HttpOnly cookie with a response from an API I'm writing. The purpose is for the cookie act like a refresh token for the purpose of silent refresh for a SPA in React.
In my controller method, I've got the following code:
response.set_cookie(
:foo,
{
value: 'testing',
expires: 7.days.from_now,
path: '/api/v1/auth',
secure: true,
httponly: true
}
)
I'm making a post request to this action with a fetch command like so:
fetch("http://localhost:3001/api/v1/auth", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'aaron#example.com',
password: '123456',
})
})
Not sure if that matters but I'm wondering if passing cookies in a XHR response doesn't work? However, this seems to be working as you can see in my response I'm getting this:
Set-Cookie: foo=testing; path=/api/v1/auth; expires=Sun, 26 Jan 2020 05:15:30 GMT; secure; HttpOnly
Also in the Network tab under Cookies I'm getting this:
However, I'm NOT getting the cookie set under Application -> Cookies:
To clarify, the React app is sitting on localhost:3000 and the rails backend is listening on localhost:3001.
Any ideas?
Ok, so it looks like I needed to configure my CORS (in Rails this is your Rack::CORS middleware.
I setup my config/initializers/cors.rb file like so:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'http://localhost:3000'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
credentials: true
end
end
and my fetch command should look something like this with credentials: 'include' as a parameter:
return fetch(`${endPoint}`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
password,
password_confirmation: passwordConfirmation
})
})
Adding credentials: true allows cookies to be set by the browser. Apparently, even if you send them, you need Access-Control-Allow-Credentials: true in the headers for the browser to do anything with them.
EDIT: Recreating this application for learning experience I came across this issue again even after including the credentials option. I wasn't seeing the HttpOnly cookie being stored in the browser. Turns out however, that it WAS and does get sent. You can probably test for this in a controller action. Keep this in mind if this solution doesn't 'seem' to work for you!

POST request works in Postman but is blocked from React front end. No CORS error, not making it to the server

I have a database setup on Dokku that is currently functioning fine with Postman. My full stack React front end and Rails back end are functioning locally, but when I attempt the same fetch calls (only difference in code is the url), the requests don't have any parameters and are blocked before ever reaching the server.
Here's an example of a fetch call I'm trying (using Redux):
export const createPurchase = purchase => {
return dispatch => {
return fetch(baseURL + 'purchases', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accepts": "application/json"
},
body: JSON.stringify({ amount: purchase.amount, bundle_name: purchase.bundleName, user_id: purchase.userId })
})
.then(resp => resp.json())
.then(userObj => {
console.log('purchase created!')
})
.catch(error => console.log(error))
}
}
Reading my Rails server logs on Dokku shows that it isn't aware that requests are being made. My CORS file looks like this:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
I'm not sure why the fetch requests are automatically getting blocked when I am allowing everything with CORS, do I need to add a header to the fetch requests?

HTTParty not sending data to API

I am trying to call a Restful API (basically a third party application). Here is my code:
resp = HTTParty.post("http://example.com/test/api/url",
{
:query => {"id"=> 3, "example_payload"=> "test payload", "details"=> {}},
:headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'client_key' => "xxx-xxx-xxxxx" }
})
This is returning a response with status "200 ok". But I am not able to find the changes in my third party application.
I tried with "Rest-client" and "Net-http" as well. Both of them are also not working.
Thanks for helping in advance.
I assume that by
"not able to find the changes in my third party application"
, you mean that your not able to hit that third party url.
Solution:
You don't need to wrap the query and headers into a hash. Simply pass them as parameters like:
HTTParty.post(
"http://example.com/test/api/url",
query: {"id"=> 3, "example_payload"=> "test payload", "details"=> {}},
headers: { 'Content-Type' => 'application/json',
'Accept' => 'application/json',
'client_key' => "xxx-xxx-xxxxx"
}
)
This works for me.

Resources