简体   繁体   中英

Elasticsearch CORS error with ReactiveSearch

I already have a Node/Express server setup for jwt authentication working with my Create React App. I'm using the CORS npm package and simple middleware app.use(cors()); to solve the expected CORS related problems and its working fine.

Now I want to add Elasticsearch and ReactiveSearch to my React app and am trying to figure out how to overcome CORS issues with my local ES instance.

My first guess is that I need to create a separate searchRoutes.js file and implement any CORS code there needed for ES to work locally and connect with my React app?

I've been following the docs for ReactiveSearch (using http-proxy-middleware) and am not having any success... keep getting this CORS error: Failed to load http://localhost:9200/query-index/_msearch ?: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

Even though I believe I have implemented the CORS preflight solution

app.options('/autocomplete', cors()); // this is for pre-flight

Any suggestions, links, or tutorials are welcomed

UPDATE: this is my Nodejs index.js (server)

require('dotenv').config();
import express from 'express';
import http from 'http';
import bodyParser from 'body-parser';
import morgan from 'morgan';
import mongoose from 'mongoose';
import proxy from 'http-proxy-middleware';
import cors from 'cors';
import compression from 'compression';

// import dotenv from 'dotenv'; // added
import router from './router';
// import { dbConfig } from './config';

// Express app init
const app = express();
// app.options('/query-index', cors()); // this is for pre-flight

/* This is where we specify options for the http-proxy-middleware
 * We set the target to appbase.io backend here. You can also
 * add your own backend url here */
const options = {
    // target: 'https://scalr.api.appbase.io/',
    target: 'http://localhost:9200',
    changeOrigin: true,
    // onProxyReq: (proxyReq, req) => {
    //     proxyReq.setHeader(
    //         'Authorization',
    //         `Basic ${btoa('cf7QByt5e:d2d60548-82a9-43cc-8b40-93cbbe75c34c')}`
    //     );
    //     /* transform the req body back from text */
    //     const { body } = req;
    //     if (body) {
    //         if (typeof body === 'object') {
    //             proxyReq.write(JSON.stringify(body));
    //         } else {
    //             proxyReq.write(body);
    //         }
    //     }
    // }
};

// Connect MongoDB
mongoose.connect(process.env.MONGODB_URI);
mongoose.set('debug', true);

// middleware
app.use(compression());
app.use(morgan('combined'));
app.use(cors()); // cors middleware
// https://stackoverflow.com/a/38345853/3125823
// Enable CORS from client-side from slatepeak
// app.use((req, res, next) => {
//   res.header('Access-Control-Allow-Origin', 'http://localhost:3333', 'http://localhost:9200'); // this can also be a list of urls
//   res.header('Access-Control-Allow-Methods', 'OPTIONS, PUT, GET, POST, DELETE');
//   res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-Auth-Token, Origin, Content-Type, Accept, Authorization, Access-Control-Allow-Credentials');
//   // res.header('Access-Control-Allow-Credentials', 'true');
//   next();
// });
app.use(bodyParser.json({ type: '*/*' }));

/* This is how we can extend this logic to do extra stuff before
 * sending requests to our backend for example doing verification
 * of access tokens or performing some other task */
app.use('/query-index', (req, res, next) => {
    const { body } = req;
    console.log('Verifying requests ✔', body);
    /* After this we call next to tell express to proceed
     * to the next middleware function which happens to be our
     * proxy middleware */
    next();
});

/* Here we proxy all the requests from reactivesearch to our backend */
app.use('/query-index', proxy(options));

app.options('/query-index', cors()); // this is for pre-flight
app.get('/query-index', cors(), function(req, res, next) {
  res.json({ msg: 'This is CORS-enabled for route \/query-index'});
});

router(app);

const authPort = process.env.PORT || 3333; // default
const authServer = http.createServer(app);
authServer.listen(authPort);
console.log('Auth Server listening on:', authPort);

First of all, you could just get rid of it and plain and simple enable CORS for all requests:

app.use(cors())

Let's assume you still want to go single-route: Your code refers to a route "autocomplete", the link you posted which returns a CORS error, is referring to a different route "query_index/..", since you chose to go single-route enabling way, you need to fix this and use the matching route where you enabled CORS.

From what you've posted your solution looks furthermore incomplete. If you look at solution :

app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

and compare it to yours, you should add a callback to your route, because the callback is where your logic happens (transfer to controller etc.). This could look like so:

app.get('/autocomplete', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for route \/autocomplete'})
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM