Hapi - enabling CORS - javascript

I am writing BE application using Node JS and Hapi (v17). While the server is running and I try to call an endpoint using POST method I keep receiving an error message:
Failed to load http://localhost:8001/login: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
I wanted to enable CORS on the server site, but nothing works for me.
here is how I enable CORS on the server site:
const hapi = require('hapi')
const server = hapi.server({
port: 8001,
host: 'localhost',
routes: {
cors: true
}
})
I was also trying to enable cors for the specific route but this also has no effect:
server.route({
method: 'POST',
path: '/login',
config: {
cors: {
origin: ['*'],
additionalHeaders: ['cache-control', 'x-requested-with']
}
},
handler: async (request, reply) => {
return User.login(request, reply)
}
})
Does anyone know what should I do to enable CORS and get rid of the problem?
Additionally, there is a screenshot from the browser's network tab:
EDIT:
I have added route that handles OPTIONS method and now I have another issue.
Failed to load http://localhost:8001/login: Request header field access-control-allow-credentials is not allowed by Access-Control-Allow-Headers in preflight response.
And here is how things look like in the network tab:

cors: {
origin: [
'*'
],
headers: ["Access-Control-Allow-Headers", "Access-Control-Allow-Origin","Accept", "Authorization", "Content-Type", "If-None-Match", "Accept-language"],
additionalHeaders: ["Access-Control-Allow-Headers: Origin, Content-Type, x-ms-request-id , Authorization"],
credentials: true
}
You should also probably define a qualified domain, instead of just * wildcard

Related

CORS redirect issue on a local development environment Laravel and Vue project

I'm having some CORS issues. In my environment I have:
Laravel project running on 127.0.0.1:8000
Vue project running on localhost:8080
This is the configuration of Vue:
const { defineConfig } = require('#vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
'/api': {
target: 'http://127.0.0.1:8000',
changeOrigin: true
},
'/sanctum': {
target: 'http://127.0.0.1:8000',
changeOrigin: true,
}
}
}
})
I'm trying to do the following requests to the Laravel server:
axios.get('sanctum/csrf-cookie').then(() => {
axios.post('api/login', {
email: email,
password: password
}).then(response => {
this.user = response.data.user
this.token = response.data.token
})
})
In the first request, the XSRF token is being set. The second request to 'api/login', however, is receiving a 302 redirection to 127.0.0.1:8000 (the /api/login route is not being considered).
The Javascript console is showing the following error:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/' (redirected from 'http://localhost:8080/api/login') from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've tried changing both client and server side configurations but I'm always going back to where I started from.
Some additional details:
if I do the login request directly toward 127.0.0.1:8000/api/login, I receive a CSRF mismatch error from Laravel (so there is not a CORS issue)
this is how the API login route is configured:
Route::post('login', '\App\Http\Controllers\Auth\LoginController#apiLogin');

Webpack devserver proxy not working to get round CORS issue

I have a React app which is running webpackdevserver on port 3000.
I have an AWS .NetCore Lambda server running localhost on port 5050.
When I try and make a request I am getting the cors error:
Access to fetch at 'http://localhost:5050/' from origin
'http://localhost:3000' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.
I was hoping to use a proxy, as per the documtation here in order to forward my requests on using the same domain to get round this.
https://medium.com/#drgenejones/proxying-an-external-api-with-webpack-serve-code-and-a-restful-data-from-separate-endpoints-4da9b8daf430
However it is not working, I don't see any difference at all with the settings applied, can anyone help?
devServer: {
port: 3000,
disableHostCheck: true,
compress: true,
host: 'localhost',
proxy: {
'/': {
target: 'http://localhost:5050',
secure: false,
},
},
},
My JavaScript to call the server is like this... I have also tried with the url http://localhost:3000 but this just returns a bad request error.
const result = await fetch('http://localhost:5050', {
method: 'POST',
headers: new Headers({ 'Access-Control-Allow-Origin': '*' }),
body: JSON.stringify({
method: 'upload',
test: 'test',
}),
});
I guess the issue is to set / which could just fetch the current server so you might need to differentiate between your web app vs your server (most likely via a specific path such as /api, but you can choose to pass this path to your proxy server or not).
So you would change as following:
Your configuration of proxy first to take api to go through proxy:
proxy: {
'/api': {
target: 'http://localhost:5050',
pathRewrite: {'^/api' : ''}, // In this case we don't pass `api` path
}
}
Next thing is to change your code to call the same domain + port 3000 normally (proxy would do the rest for you by passing to your server with port 5050 which you configured):
const result = await fetch('http://localhost:3000/api', {
// ...
});

cors working on localhost but not on production

I'm having a strange issue with express cors. My Cors config works fine on localhost but it isn't working on the production. I'm always getting this error.
Failed to load
https://my-movie-db-backend-roberto.herokuapp.com/auth/login: Response
to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://my-movie-db-roberto.herokuapp.com' is
therefore not allowed access. The response had HTTP status code 503.
If an opaque response serves your needs, set the request's mode to
'no-cors' to fetch the resource with CORS disabled.
This is my cors configuration:
import * as cors from "cors";
const corsConfig: cors.CorsOptions = {
origin: ["https://my-movie-db-roberto.herokuapp.com", "http://localhost:3000"],
credentials: true,
methods: "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE"
};
app.use(cors(corsConfig));
// add your routes
<MY-Routes>
// enabling pre-flight
app.options("*", cors(corsConfig));
I have been around this for some time now and I decide that it would be better ask for help, thanks ;-)
I tried to replicate the setup and found that the cors library seems to not send the Access-Control-Allow-Origin header if the origin is not on the list of allowed origins.
So make sure you don't have any typos in the entries for that option or try with "*" first and then refine in a second step.
Here is the code I'm using:
Server side
var express = require('express')
var cors = require('cors')
const app = express()
const corsConfig = {
origin: ["http://testing.local", "https://my-movie-db-roberto.herokuapp.com", "http://localhost:3000"],
credentials: true,
methods: "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
allowedHeaders: ['Content-Type']
};
app.use(cors(corsConfig));
enter code here
// add your routes
app.post('/', (req, res) => res.send('yay'));
// enabling pre-flight
app.options("*", cors(corsConfig));
app.listen(8080, () => console.log('serving...'))
Client (http://testing.local):
fetch('http://localhost:8080/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
.then(r => r.text())
.then(console.log)
Apparently the problem it wasn't on the cors at all. The backend server it was offline due to some missing packages that were considered dev dependencies and Heroku didn't installed them. Just change the isProduction flag on Heroku and all works fine now.

hapi.js cors with auth

Put together the below.
server.route([
{
method: "POST",
path: "/authorize",
config: {
auth: false,
cors: {
origin: ['*']
}
},
handler: (request, reply) => {
...
reply.redirect(redirectUrl)
}
}
])
I want to use with client-side JavaScript browser fetch API. The cors part is necessary to avoid using the no-cors mode for fetch and to get a non-opaque response.
If I use only 'authin the config section or onlycors` they work fine, but together hapi complaints that the configuration is wrong.
Why is that?
inside config object you cannot use key cors. for correct configuration you have to put cors key inside this like this
server.connection({
port: dbConfig.port,
routes: { cors: true } // set cross origin by hapi inbuilt property
// tls: tls
})

Cannot POST with content-type: application/json from angular to rails

So I am trying to send a POST request with Content-Type: application/json from angular to my rails backend. I get the following error in console:
angular.js:12578 OPTIONS http://localhost:3000/api/student_create 404 (Not Found)
and
XMLHttpRequest cannot load http://localhost:3000/api/student_create. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8008' is therefore not allowed access. The response had HTTP status code 404.
Note the post request works properly when I use Content-Type: application/x-www-form-urlencoded
It also works in Postman with the application/json Content-Type set in the header.
Angular Controller:
.controller('View1Ctrl', function($scope, $http) {
var data = {
name: "name"
};
$http({
url: 'http://localhost:3000/api/student_create',
dataType: 'json',
method: 'POST',
data:data,
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
}).then(function(response) {
console.log(response)
}, function(error) {
console.log(error)
});
});
API controller (Rails):
class ApiController < ApplicationController
before_action :set_headers
skip_before_action :verify_authenticity_token
def set_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
end
def create_student
student = StudentUser.new
student.name= params[:name]
student.save
render json: "test".to_json #temporary
end
route: post 'api/student_create' => 'api#create_student'
Edit: frontend is on http://localhost:8008, backend is on localhost:3000
Hi I too faced this problem when i was interacting Rails with Angular.
After lot of research i found gem 'rack-cors' which solved this issue. You can follow its documentation here. Rails by default doesn't allow cross origin resource sharing. So basically it handles cross origin requests nicely.
Steps:
Install the gem:
gem install rack-cors
Or in your Gemfile:
gem 'rack-cors', :require => 'rack/cors'
application.rb file
module YourApp
class Application < Rails::Application
# ...
# Rails 3/4
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
# Rails 5
config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
end
end
Try the following, from How to Configure CORS Accept Headers in Rails API Application
So, even if your consumer is on “localhost:3000” and your provider is on “localhost:3001”, the response will be neglected unless your web service sets a permissive CORS policy. This policy is defined by the provider setting specific CORS headers in HTTP response that a consumer app (e.g. a browser) destined to enforce. For example, configuring these headers:
# in config / application.rb
config.action_dispatch.default_headers = {
'Access-Control-Allow-Origin' => 'http://my-web-service-consumer-site.com',
'Access-Control-Request-Method' => % w {
GET POST OPTIONS
}.join(",")
}
Per site:
Please note, that setting 'Access-Control-Allow-Origin' => '*' is highly discouraged, unless you are providing a public API that is intended to be accessed by any consumer out there.

Categories