Vite proxy server does not rewrite POST requests - node.js

After setting up a proxy using Vite, it only proxies GET and HEAD requests.
I need other methods to also be proxied.
on a fresh vite react project - only thing I touched was vite.config.ts
import { defineConfig } from 'vite'
import react from '#vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/test': {
target: 'http://jsonplaceholder.typicode.com',
rewriteHost: true,
}
}
}
})
curl -X POST localhost:3000/test causes the following log message when run with vite --debug
vite:html-fallback Not rewriting POST /test because the method is not GET or HEAD. +1ms
But instead I expected this to POST to https://google.com/test

I solved it. The above config actually works. I found the error at the very top of the logs when starting the server. (in my case it was a bunch of DNS stuff I did not understand when proxying to Google - changeing to the example on vite's page worked)
I think as soon as you use a Regex - it only allows GET or HEAD. (unsure - but not using a regex fixed it for me)

Related

File serve in shopify app dev not working

I've created shopify app with node.js app template
npm init #shopify/app#latest
Folder structure is at the bottom
And run npm run dev
It's ok for api endpoints.
What I wanna do is to serve static files. In fact, this is an express.js server and I created a static folder in web folder
app.use(serveStatic('static'));
But I can't access static files. I tried app.use(serveStatic("${process.cwd()}/static")). The above stuff is working on a normal express.js project. But it does not work with shopify cli and vite config.
Vite config is
const config = {
test: {
globals: true,
exclude: ["./frontend/**", "./node_modules/**"],
},
};
export default config;
I finally got it.
I noticed that:
It works if you were to load using localhost:PORT/path/to/static.file. You can print out PORT in your web/index.js.
This simple middleware doesn't get triggered when requesting your static file through ngrok but it does get triggered by number 1 above.
app.use((req, res, next) => {
console.log("Backend hit!");
next();
});
That means the backend never got the static file request. My understanding is vite receives all the requests then proxies some of them to the backend using a config.
The config Shopify gave is not proxying the static file request so you'll need to modify the proxy config.
vite.config
...
export default defineConfig({
...
server: {
host: "localhost",
port: process.env.FRONTEND_PORT,
hmr: hmrConfig,
proxy: {
"^/(\\?.*)?$": proxyOptions,
"^/api(/|(\\?.*)?$)": proxyOptions,
// The next line is what I added
"^/static/.*$": proxyOptions,
},
},
});
web/index.js
app.use("/static", express.static(`${process.cwd()}/public`));
I'm mounting my static files on "/static" but feel free to modify the proxy line to suit your needs.

Problems with vue router (history mode) in development server Vue.js - “Cannot GET /config”

I just wanted to setup my vue project with the full webpack template, use vue router and link different urls to different components.
The src/router/index.html is the following:
import Vue from 'vue';
import Router from 'vue-router';
// eslint-disable-next-line
import Home from '../pages/home.vue';
// eslint-disable-next-line
import Config from '../pages/config.vue';
Vue.use(Router);
export default new Router({
mode: 'hash',
routes: [
{ path: '/', component: Home },
{ path: '/config', component: Config },
],
});
When I run npm run dev and access the above routes, I have the following output:
Up to here, everything is working fine. The problem is when I use the history mode, I can’t access to localhost:8080/config:
And the console doesn’t show any error:
Another thing I tried was switching the mode to history using the simple-webpack template. The worst part is that it worked! So, the problem is in the webpack-template, but I don't know how to make this work.
I'll appreciate any help.

How to configure a proxy in Angular CLI

I created a new #angular/cli project and added one http GET call in the root component. Without using a proxy this works fine.
export class AppComponent implements OnInit {
constructor(private http: Http) {}
ngOnInit() {
this.http
.get('https://dog.ceo/api/breeds/list/all')
.map(response => response.json())
.subscribe(data => console.log(data));
}
}
When I try to add the configure as describe in the Angular CLI wiki things go wrong.
My proxy.conf.json file:
{
"/api": {
"target": "https://dog.ceo",
"secure": false
}
}
I changed the URL in the component to /api/breeds/list/all. And I ran ng serve --proxy-config proxy.conf.json
Then I'm gertting Internal Server Error message in my browsers console. And in the terminal where I started ng serve I'm getting this message [HPM] Error occurred while trying to proxy request /api/breeds/list/all from localhost:4200 to https://dog.ceo (EPROTO)
(https://nodejs.org/api/errors.html#errors_common_system_errors)
I have tried several other configuration options and multiple API's. Results are similar.
The complete code is available on GitHub: https://github.com/ErikNijland/angular-cli-proxy-test
Versions used:
#angular/cli: 1.3.0
NodeJS: v8.1.4
Note: I understand that #angular/cli is using Webpack. Which in turn is using http-proxy-middleware.
I think it is happening because of the origin your are asking https from http. This can be solved using a flag in your proxy.
{
"/api": {
"target": "https://dog.ceo",
"secure": false,
"changeOrigin": true
}
}

How to setup a proxy using web sockets and angular CLI

I have a simple web app built using the angular CLI. I want it to communicate with a backend using web sockets. I have the backend already written and have tested with a simple index.html page that the server can send and receive on sockets.
In my angular-cli project I have setup a proxy config file to setup a proxy to the backend.
proxy.conf.json
{
"/sock": {
"target": "http://localhost:3000",
"changeOrigin": true,
"ws": true,
"logLevel": "debug"
}
}
Then start the server with the following.
ng serve --proxy-config proxy.conf.json
For now I have a service that simply attempts to open a socket and send a fixed string which I'm expecting to see logged by the backend.
import { Injectable } from '#angular/core';
import * as io from 'socket.io-client';
#Injectable()
export class ChatService {
private socket: any;
constructor() {
this.socket = io({ 'path': '/sock' });
this.socket.emit('chat message', 'Hello World from browser!');
}
}
Note: I've had several go's at this with and without the /sock part of the url.
I start both servers. Get no console errors in the browser. But in the angular CLI web pack server I get the following messages.
10% building modules 2/2 modules 0 active[HPM] Proxy created: /sock -> http://localhost:3000
[HPM] Subscribed to http-proxy events: [ 'error', 'close' ]
[HPM] GET /sockjs-node/530/z1z3teld/websocket -> http://localhost:3000
[HPM] Upgrading to WebSocket
[HPM] Error occurred while trying to proxy request /sockjs-node/530/z1z3teld/websocket from localhost:4200 to http://localhost:3000 (ECONNRESET) (https://nodejs.org/api/errors.html#errors_common_system_errors)
Are web sockets supported or have I made a silly mistake?
Thanks
I managed to figure it out with a bit of trial and error. I looked at the console for the basic index.html page that works within the backend project. This backend project is basically the chat server demo application on the socket.io website. I noticed that when it opens up the web socket the url looks like the following:
http://localhost:3000/socket.io/EIO=3&transport=websocket&sid=wTvdQTclHXJSUmAmAAAA
So back in the angular CLI project I modified my proxy config to include the /socket.io/ part plus also added a wildcard.
{
"/sock/*": {
"target": "http://localhost:3000/socket.io/",
"ws": true,
"logLevel": "debug"
}
}
Bingo! Now when the service is constructed it opens the socket and emits a message which I can see logged in the backend.

How to setup gulp browser-sync for a node / react project that uses dynamic url routing

I am trying to add BrowserSync to my react.js node project. My problem is that my project manages the url routing, listening port and mongoose connection through the server.js file so obviously when I run a browser-sync task and check the localhost url http://localhost:3000 I get a Cannot GET /.
Is there a way to force browser-sync to use my server.js file? Should I be using a secondary nodemon server or something (and if i do how can the cross-browser syncing work)? I am really lost and all the examples I have seen add more confusion. Help!!
gulp.task('browser-sync', function() {
browserSync({
server: {
baseDir: "./"
},
files: [
'static/**/*.*',
'!static/js/bundle.js'
],
});
});
We had a similar issue that we were able to fix by using proxy-middleware(https://www.npmjs.com/package/proxy-middleware). BrowserSync lets you add middleware so you can process each request. Here is a trimmed down example of what we were doing:
var proxy = require('proxy-middleware');
var url = require('url');
// the base url where to forward the requests
var proxyOptions = url.parse('https://appserver:8080/api');
// Which route browserSync should forward to the gateway
proxyOptions.route = '/api'
// so an ajax request to browserSync http://localhost:3000/api/users would be
// sent via proxy to http://appserver:8080/api/users while letting any requests
// that don't have /api at the beginning of the path fall back to the default behavior.
browserSync({
// other browserSync options
// ....
server: {
middleware: [
// proxy /api requests to api gateway
proxy(proxyOptions)
]
}
});
The cool thing about this is that you can change where the proxy is pointed, so you can test against different environments. One thing to note is that all of our routes start with /api which makes this approach a lot easier. It would be a little more tricky to pick and choose which routes to proxy but hopefully the example above will give you a good starting point.
The other option would be to use CORS, but if you aren't dealing with that in production it may not be worth messing with for your dev environment.

Resources