Create API in a Vue/Quasar SSR project - ajax

I want to create an API that can be called by the app itself (whether "ajax" or server-rendered) and other clients (e.g. mobile app). Most of the articles I found when googling "Quasar REST API" talk about how to access external APIs, which is not my case.
My understanding is to modify src-ssr/extension.js:
module.exports.extendApp = function({app, ssr}) {
app.get('/api/bla', (req, res) => {
res.send('something')
})
}
and ensure port inside src-ssr/index.js:
const ssr = require('../ssr'),
extension = require('./extension'),
app = express(),
port = process.env.PORT || 8888
matches the value in quasar.conf.js:
devServer: {
https: false,
open: false,
port: 8888,
},
The project builds and runs successfully, but http://localhost:8888/api/bla keeps loading in the browser. What do I miss?

Related

Using Express Router to proxy non-CORS content doubles request path

There must be something obvious I am missing. I have an external record like https/udspace.udel.edu/rest/handle/19716/28599 that is not set up for CORS, but I would like to get access to it in my application. In the past, I have set up a server to simply GET the resource and redeliver it for my application. However, I read about Node http-proxy-middleware and thought I'd try out a more direct proxy.
First, I could not use the target in the createProxyMiddleware() constructor because I wanted to send in the hostname and path of the desired resource like, perhaps, http://example.com/https/udspace.udel.edu/rest/handle/19716/28599 to get the resource above.
Relevant Code (index.js)
const express = require('express')
const { createProxyMiddleware } = require('http-proxy-middleware')
const app = express()
app.get('/info', (req, res, next) => {
res.send('Proxy is up.');
})
// Proxy endpoint
app.use('/https', createProxyMiddleware({
target: "incoming",
router: req => {
const protocol = 'https'
const hostname = req.path.split("/https/")[1].split("/")[0]
const path = req.path.split(hostname)[1]
console.log(`returning: ${protocol}, ${hostname}, ${path}`)
return `${protocol}://${hostname}/${path}`
},
changeOrigin: true
}))
app.listen(PORT, HOST, () => {
console.log(`Starting Proxy at ${HOST}:${PORT}`);
})
I was getting a 404 from the DSpace server without other information, so I knew that the request was going through, but transformed incorrectly. I tried again with an item in an S3 bucket, since AWS gives better errors and saw that my path was being duplicated:
404 Not Found
Code: NoSuchKey
Message: The specified key does not exist.
Key: api/cookbook/recipe/0001-mvm-image/manifest.json/https/iiif.io/api/cookbook/recipe/0001-mvm-image/manifest.json
What dumb thing am I doing wrong? Is this not what this proxy is for and I need to do something else?

Socket IO forbidden 403

I have a simple socket.io app and it works just fine on local and also it's installed successfully on AWS server using plesk admin dashboard but when I connect to the app I always get forbidden {"code":4,"message":"Forbidden"} .. the entry point seems to work great http://messages.entermeme.com .. any idea what could be wrong with it ?
Frontend code
import io from 'socket.io-client'
const socket = io('https://messages.entermeme.com', {
transports: ['polling'],
})
socket.emit('SUBSCRIBE')
Backend code
const cors = require('cors')
const app = require('express')()
const server = require('http').Server(app)
const io = require('socket.io')(server)
server.listen(9000)
app.use(cors())
io.set('transports', [
'polling'
])
io.origins([
'http://localhost:8000',
'https://entermeme.com',
])
io.on('connection', (socket) => {
socket.on('SUBSCRIBE', () => {
//
})
})
had a similar issue but when using nginx. So in case you still need some help:
In the end it turned out to be the URL I specified as socket origins. I didn't specify the port since the origin for me was also running on port 80 (443 for SSL) like in your example above:
io.origins([
'http://localhost:8000',
'https://entermeme.com', // <--- No port specified
])
I updated my config and added the port. So for you it would be:
io.origins([
'http://localhost:8000',
'https://entermeme.com:80', // <--- With port (or 443 for SSL)
])

Nuxt Axios Dynamic url

I manage to learn nuxt by using following tutorial
https://scotch.io/tutorials/implementing-authentication-in-nuxtjs-app
In the tutorial, it show that
axios: {
baseURL: 'http://127.0.0.1:3000/api'
},
it is point to localhost, it is not a problem for my development,
but when come to deployment, how do I change the URL based on the browser URL,
if the system use in LAN, it will be 192.168.8.1:3000/api
if the system use at outside, it will be example.com:3000/api
On the other hand, Currently i using adonuxt (adonis + nuxt), both listen on same port (3000).
In future, I might separate it to server(3333) and client(3000)
Therefore the api links will be
localhost:3333/api
192.168.8.1:3333/api
example.com:3333/api
How do I achieve dynamic api url based on browser and switch port?
You don't need baseURL in nuxt.config.js.
Create a plugins/axios.js file first (Look here) and write like this.
export default function({ $axios }) {
if (process.client) {
const protocol = window.location.protocol
const hostname = window.location.hostname
const port = 8000
const url = `${protocol}//${hostname}:${port}`
$axios.defaults.baseURL = url
}
A late contribution, but this question and answers were helpful for getting to this more concise approach. I've tested it for localhost and deploying to a branch url at Netlify. Tested only with Windows Chrome.
In client mode, windows.location.origin contains what we need for the baseURL.
# /plugins/axios-host.js
export default function ({$axios}) {
if (process.client) {
$axios.defaults.baseURL = window.location.origin
}
}
Add the plugin to nuxt.config.js.
# /nuxt.config.js
...
plugins: [
...,
"~/plugins/axios-host.js",
],
...
This question is a year and a half old now, but I wanted to answer the second part for anyone that would find it helpful, which is doing it on the server-side.
I stored a reference to the server URL that I wanted to call as a Cookie so that the server can determine which URL to use as well. I use cookie-universal-nuxt and just do something simple like $cookies.set('api-server', 'some-server') and then pull the cookie value with $cookies.get('api-server') .. map that cookie value to a URL then you can do something like this using an Axios interceptor:
// plguins/axios.js
const axiosPlugin = ({ store, app: { $axios, $cookies } }) => {
$axios.onRequest ((config) => {
const server = $cookies.get('api-server')
if (server && server === 'some-server') {
config.baseURL = 'https://some-server.com'
}
return config
})
}
Of course you could also store the URL in the cookie itself, but it's probably best to have a whitelist of allowed URLs.
Don't forget to enable the plugin as well.
// nuxt.config.js
plugins: [
'~/plugins/axios',
This covers both the client-side and server-side since the cookie is "universal"

Ajax With ReactJS to NodeJS

I'm using webpack-dev-server while developing in ReactJS.
I also want to add a backend which will be written in NodeJS.
When I run the webpack-dev-server it binds to port 8080.
When I run node, it can't bind to the same port.
Therefore, I'm unable to perform $.ajax requests due to the SOP.
How do I get over this issue?
NodeJS:
const express = require('express');
const app = express();
app.get('/messages', function(req, res){
res.send('hello world!');
});
let server = app.listen(8081, function() {
const host = server.address().address;
const port = server.address().port;
console.log('Listening at http://%s:%s', host, port);
});
React/JS/Ajax:
$.getJSON('/messages', function(data) {
this.setState({
messages: data
});
}.bind(this));
And I'm running webpack-dev-server without any parameters.
the port of app is different from the portof your server. if you want to keep save port, you can try to use webpack proxy
module.exports = {
// the other config of your webpack
devServer: {
hot: true,
historyApiFallBack: true,
proxy: {
'/message': {
target: 'http://localhost:8081',
secure: false,
changeOrigin: true
},
},
},
}
when you fetch http://localhost:8080/messages, webpack-dev-server will proxy to http://localhost:8080/messages.
Your app is on port 8080.
Your server is on 8081.
If you want to request from the server, you need to specify the port to the server. If not, it will request to the port your app is running to, which is 8080.
$.getJSON('https://localhost:8081/messages', function(data) {
this.setState({
messages: data
});
}.bind(this));

Reverse proxy Ghost (Heroku app) from another app (expressjs)

Simple case: I have app1 - which is an install of ghost (site-blog.herokuapp.com). I have app2, which is a custom express.js app (site.herokuapp.com).
I want to serve the blog from site.herokuapp.com/blog.
For Ghost, here's part of my config.js
production: {
url: process.env.BLOG_IDENTIFIER_URL,
fileStorage: false,
database: {
client: 'postgres',
connection: process.env.DATABASE_URL,
debug: false
},
server: {
host: '0.0.0.0',
port: process.env.PORT
}
},
BLOG_IDENTIFIER_URL is set to site.herokuapp.com/blog.
For the express.js app, I have the following routing (for /blog):
router.all('*', function(req, res) {
// blog page is actually a ghost!
var blog_url = 'http://localhost:2368';
if (process.env.NODE_ENV === 'production') {
blog_url = 'http://site-blog.herokuapp.com';
}
req.headers.host = blog_url;
require('http-proxy').createProxyServer().web(req, res, { target: blog_url });
});
This works absolutely fine locally, but when I push both the repos to heroku, and try to visit site.herokuapp.com/blog, I get just a blank page and nothing in the logs. The request fails though:
I have tried a lot of stuff, both from SO and from the rest of the visible internet. Nothing seems to work. I'm stuck here for the last 4 hours. If you have anything that might help, please please leave a comment or an answer.

Resources