Cannot call api route from client app loaded by distant browser - api

I have a server where there is an api running on port 8081 and a client Vue app running on 8082.
My client app using Axios to make queries to the api using the following code.
const api = axios.create({
baseURL: 'http://127.0.0.1:8081/api/route',
headers: {
'Content-Type': 'text/plain',
},
});
The client is served by the following express server :
const express = require("express");
const cors = require("cors");
const path = __dirname + '/dist/';
const app = express();
app.use(express.static(path));
app.use(cors());
app.get('*', function (req,res) {
res.sendFile(path + "index.html");
});
// set port, listen for requests
const PORT = 8082;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
If I use my app directly from the server there is no problem, the query is correctly executed.
But if I load the app from a distant browser, the client is not capable to execute the query, trying to use the 127.0.0.1 of the distant browser, not the server one.
Error case with browser
Setting Axios to use the local IP of the server make the things work but the application need to be generic and it should only use the 127.0.0.1 because the app and api will always be on the same machine.

I found the solution, to make the address generic, I need to use the global variable:
window.location.hostname
That contains the hostname of the machine that runs the Vue app server.
Now when I try to make a request from distant computer, my browser is correctly using the machine hostname, not its own localhost.
This is the new Axios configuration :
const apo = axios.create({
baseURL: `http://${window.location.hostname}:8081/api/route`,
headers: {
'Content-Type': 'text/plain',
},
});

Related

Do we face any issues with creating apollo server and converting it to express server using apollo/server npm package?

pls check the below code,
// npm install #apollo/server express graphql cors body-parser
import { ApolloServer } from '#apollo/server';
import { expressMiddleware } from '#apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '#apollo/server/plugin/drainHttpServer';
import express from 'express';
import http from 'http';
import cors from 'cors';
import bodyParser from 'body-parser';
import { typeDefs, resolvers } from './schema';
// Required logic for integrating with Express
const app = express();
// Our httpServer handles incoming requests to our Express app.
// Below, we tell Apollo Server to "drain" this httpServer,
// enabling our servers to shut down gracefully.
const httpServer = http.createServer(app);
// Same ApolloServer initialization as before, plus the drain plugin
// for our httpServer.
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});
// Ensure we wait for our server to start
await server.start();
// Set up our Express middleware to handle CORS, body parsing,
// and our expressMiddleware function.
app.use(
'/',
cors(),
bodyParser.json(),
// expressMiddleware accepts the same arguments:
// an Apollo Server instance and optional configuration options
expressMiddleware(server, {
context: async ({ req }) => ({ token: req.headers.token }),
}),
);
// Modified server startup
await new Promise((resolve) => httpServer.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000/`);
The code is from official documentation of apollo server, My question is, here we are first creating an apollo server and converting it to express server using expressMiddleware(server),
Will there be any issues with this conversion ?
Will we face any lack of control over the converted express server ?
My question is, here we are first creating an apollo server and converting it to express server using expressMiddleware(server),
That's not what you're doing at all.
You created an express server (const app = express()).
You created a separate http server from that app.
You created a running executable GraphQL Server.
You created an express middleware ((req, res, next) => void) that generates a context of { token?: string }, parses the body of your request into a GraphQL payload and then executes against the GraphQL Server with that context and with that payload.
You then added that express middleware to a route you created at "/", along with other middleware you attached before it.
You started the httpServer you created in #2
Will there be any issues with this conversion ?
Will we face any lack of control over the converted express server ?
This is no conversion, as mentioned. Hopefully you now understand that.
You created all of those things. Your express app is a variable called app. Do whatever you want with it. Your http server is a variable called httpServer. Do whatever you want with it.

I'm having trouble with axios get and post requests in real host

When I'm on the local server localhost:8080 in vue project everything is great, but when I deploy the project to my real host I get the problem
mounted(){
axios.get('http://localhost/online-store/src/database_api/Admin/recent_product.php')
.then((res) => {
this.products= res.data
console.log(res.data)
})
},
configure your axios in main.js (entry point )
axios.create({
baseURL: process.env.VUE_APP_BASE_URL
})
Then directly call api ..it will append base url based on your env parameter
axios('/online-store/src/database_api/Admin/recent_product.php')
Note : Don't forget to add .env as per environment

Mocking API calls with Detox and Nock

I'm trying to mock API calls from Detox tests and nothing seems to be working. Nock in theory would do exactly what I want but there when I run my tests with nock debugging it isn't seeing any of the requests being made from my app. I'm using axios to make requests and I've tried setting the adapter on my axios instance to the http adapter.
Any suggestions on how to get nock working with Detox or if there is another mocking library you have had success with is appreciated, thanks!
What I ended up doing was leveraging the mocking specified in Detox docs (a separate *.e2e.js file hitting a different endpoint during tests). You define these special files that only run during e2e, I've set mine up to only hit localhost:9091 -- I then run an Express server on that port serving the endpoints I need.
Maybe an ugly way to do it, would love suggestions!
My mock file:
// src/helpers/axios.e2e.js
import axios from 'axios';
const instance = axios.create({
baseURL: `http://localhost:9091/api`,
});
export default instance;
Here's how I am running an express server during tests:
// e2e/mytest.e2e.js
const express = require('express');
let server;
beforeAll(async () => {
const app = express();
app.post('/api/users/register/', (req, res) => {
res.status(400)
res.send({"email": ["Test error: Email is required!"]})
})
await new Promise(function(resolve) {
server = app.listen(9091, "127.0.0.1", function() {
console.log(` Running server on '${JSON.stringify(server.address())}'...`);
resolve();
});
});
})
afterAll(() => {
server.close()
})

Problem deploying only Apollo Server to heroku

I am deploying an Apollo Server for my database to heroku and it is giving an application error. It is not simply show that there is a problem with the get route, it says that the application has an error and the error logs say that the app is crashing. It runs fine locally.
I have set up the procfile with: web: node app.js .
I have tried it with the procfile removed.
I have set playground and introspection to true. I saw that that could be the problem but it did not seem to help.
The port is set to process.env.PORT || 8080 .
Here is the minimal code:
const { ApolloServer } = require('apollo-server-express');
const express = require('express');
const db = require('./models');
const typeDefs = require('./data/schema');
const resolvers = require('./data/resolvers');
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
context: { db },
introspection: true,
playground: true,
});
server.applyMiddleware({ app });
const PORT = process.env.PORT || 8080;
app.get('/', (req, res) => {
res.send('hello');
});
app.listen(PORT, () => {
console.log(`Server is ready at ${PORT}`);
});
I am also using some other functions (trying to set up a cron process), but those are commented out.
I would expect to get the / get route to at least say hello, or for the /graphql route to display playground. I am getting neither of those options.
It turns out that I needed to add the following to package.json:
"scripts": {
"start": "app.js",
...
}
And I needed to install packages listed in the heroku logs --tail, but I have had those errors before. Writing the script start key into the package.json file is for when you are deploying your server independently of your react (or client) side.

Running a Parse app locally on WebStorm

I have recently started working with a new stack of technologies and need some help.
I'm working on an existing parse.com app. The guys have been using Sublime 2.
I'm trying to get the app running on WebStorm. After doing some research and trying a couple of things I still can't run it locally.
I have created a new Node.js Express app using WebStorm and that works beautifully, so I'm assuming my environment (WIN10) is set up correctly.
I had to create an package.json for it and change some libraries around like bodyParser (it was using Parse.BodyParser, which is deprecated AFAIK)
I installed all packages/plugins using npm, and WebStorm is no longer complaining about missing references ect..
Here is the first lines:
var express = require('express');
var parseExpressHttpsRedirect = require('parse-express-https-redirect');
var parseExpressCookieSession = require('parse-express-cookie-session');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var app = express();
app.set('views', 'cloud/views');
app.set('view engine', 'ejs');
app.use(parseExpressHttpsRedirect()); // Require user to be on HTTPS.
app.use(bodyParser);
app.use(cookieParser('SecretCodeHere'));
app.use(parseExpressCookieSession({
cookie: {
maxAge: 86400000
}
}));
And then we have this gem at the end of the file:
app.listen();
Now I'm assuming that this works because this gets deployed to parse.com and it does some Magic to host it.
Now the app starts when I run it but I cant connect to it.
I've tried the following:
Connecting to https://localhost:63342/ProjectName/ (this is the default behavior AFAIK) after running gives me 404 Not Found Index file doesn't exist.
Changing the code to :
app.listen(3000, function () {
console.log('App listening on port 3000!');
});
That gives me localhost unexpectedly closed the connection. ERR_CONNECTION_CLOSED
Is there anything else I can try?
If you want to host the server on port 3000, you would need to import the http module
import http = require('http');
http.createServer(app).listen(3000, function () {
console.log('Express server listening on port 3000'));
});