SvelteKit's how to omit host address in fetch url under proxy - sveltekit

I've configured proxy, so http://localhost:3000/api/articles goes to http://127.0.0.1:8000/articles
svelte.config.js:
const config = {
kit: {
target: '#svelte',
vite: {
server: {
proxy: {
'/api': {
target: 'http://127.0.0.1:8000',
rewrite: (path) => path.replace(/^\/api/, ''),
changeOrigin: true,
}
}
}
}
}
};
And requests like this works just fine:
<script context="module">
export const load = async ({ fetch }) => {
const res = await fetch('http://localhost:3000/api/articles');
...
}
</script>
But they do not work if host is omitted:
<script context="module">
export const load = async ({ fetch }) => {
const res = await fetch('/api/articles');
...
}
</script>
res contains 404 error
Playing with https://kit.svelte.dev/docs#configuration-host did not help
So, is it possible to omit host in load's fetch under proxy?

Thank you for sharing your vite configuration. I'm using #sveltejs/kit#1.0.0-next.522, which runs in dev mode on Port 5173 and i am runnig an http-server on port 8080, which simply responses »Good morning, world!«.
// vite.config.ts
import { sveltekit } from '#sveltejs/kit/vite';
import type { UserConfig } from 'vite';
const config: UserConfig = {
plugins: [sveltekit()],
server: {
proxy: {
'/api': {
target: 'http://[::1]:8080',
rewrite: (path) => path.replace(/^\/api/, ''),
changeOrigin: true
}
}
}
};
export default config;
// src/routes/hello/+page.svelte
<script lang="ts">
const hi = fetch('/api').then((x) => x.text());
</script>
{#await hi}
<p>Loading ...</p>
{:then data}
<p>Greeting: {data}</p>
{:catch error}
<p>Error {error.message}</p>
{/await}
On http://127.0.0.1:5173/hello my browser renders first Loading ... and then settles to Greeting: Good morning, world!.

Related

Nextjs urql subscription exchange import problem

i can't get urql subscriptions to work with NextJS because of imports problem.
Basically i'm using this graphql-ws lib that is recommended in urql docs, that needs ws implementation library (eg: 'ws'). And when i import WebSocket from 'ws' i get this error: Module not found: Can't resolve 'net'
import { createClient, defaultExchanges, subscriptionExchange, Client } from 'urql';
import { createClient as createWSClient } from 'graphql-ws';
import WebSocket from 'ws'; // <-- This causes the error
export const createUrqlClient = (): Client => {
const wsClient = createWSClient({
url: 'ws://xxx/graphql',
webSocketImpl: WebSocket,
});
const client = createClient({
url: 'http://xxx/graphql',
exchanges: [
...defaultExchanges,
subscriptionExchange({
forwardSubscription: operation => ({
subscribe: sink => ({
unsubscribe: wsClient.subscribe(operation, sink),
}),
}),
}),
],
});
return client;
};
I tried nextjs dynamic import and both of these didn't work as well:
const WebSocket = dynamic(() => import('ws'), { ssr: false });
const WebSocket = dynamic(() => import('ws').then(module => module.default), { ssr: false });
I also tried to alter webpack config in next.config.js to not bundle these libs at all:
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback = {
child_process: false,
process: false,
fs: false,
util: false,
http: false,
https: false,
tls: false,
net: false,
crypto: false,
path: false,
os: false,
stream: false,
zlib: false,
querystring: false,
events: false,
'utf-8-validate': false,
bufferutil: false,
};
}
return config;
},
but then i get these errors:
./node_modules/ws/lib/validation.js
Module not found: Can't resolve 'utf-8-validate' in '/home/danko/app/node_modules/ws/lib'
warn - ./node_modules/ws/lib/buffer-util.js
Module not found: Can't resolve 'bufferutil' in '/home/danko/app/node_modules/ws/lib'
if i add 'utf-8-validate': false and bufferutil: false to the cfg as well i get this err:
TypeError: Class extends value undefined is not a constructor or null
So basically nothing works properly then as you can see...
How hard can this be, i can't be the only person that uses urql subscriptions with nextjs, hope somebody can help me with this. Thanks!
Basically as i thought, impl was not needed because native html5 websocket can be used, problem was trash nextjs with it's server side thing.
I pretty much don't use that exchange when typeof window !== 'undefined'
this is the working code:
import { createClient, dedupExchange, cacheExchange, subscriptionExchange, Client, Exchange } from 'urql';
import { multipartFetchExchange } from '#urql/exchange-multipart-fetch';
import { createClient as createWSClient } from 'graphql-ws';
export const createUrqlClient = (): Client => {
const graphqlEndpoint = process.env!.NEXT_PUBLIC_GRAPHQL_ENDPOINT as string;
const graphqlWebsocketEndpoint = process.env!.NEXT_PUBLIC_GRAPHQL_WS_ENDPOINT as string;
let exchanges: Exchange[] | undefined = [dedupExchange, cacheExchange, multipartFetchExchange];
if (typeof window !== 'undefined') {
const wsClient = createWSClient({
url: graphqlWebsocketEndpoint,
});
const subExchange = subscriptionExchange({
forwardSubscription: operation => ({
subscribe: sink => ({
unsubscribe: wsClient.subscribe(operation, sink),
}),
}),
});
exchanges.push(subExchange);
}
const client = createClient({
url: graphqlEndpoint,
requestPolicy: 'cache-and-network',
exchanges,
fetchOptions: () => ({
credentials: 'include',
}),
});
return client;
};
#dankobgd
I had the same problem and your answer helped me.
I simplified a bit and it's working
export const client = (): Client => {
let exchanges: Exchange[] = [...defaultExchanges]
if (typeof window !== 'undefined') {
const wsClient = createWSClient({
url: wsUrl,
})
const subExchange = subscriptionExchange({
forwardSubscription: (operation) => ({
subscribe: (sink) => ({
unsubscribe: wsClient.subscribe(operation, sink),
}),
}),
})
exchanges.push(subExchange)
}
return createClient({
url,
exchanges,
})
}

Proxying requests in a create-react-app application

I have been looking all over to try and figure out why this doesn't work. I have two applications, a client and a server. I'd like to proxy the client requests to the server. I have a route called /api/repositories. I can't have the proxy in the package.json, because it needs to work in production, also.
It is a Create React App project. Here are the important files.
setupProxy.js
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = (app) => {
app.use(
createProxyMiddleware("/api", {
target: "http://my.server.com",
changeOrigin: true,
onProxyReq: (proxyReq) => {
console.log("logged");
if (proxyReq.getHeader("origin")) {
proxyReq.setHeader("origin", "http://my.server.com");
}
},
})
);
};
And I use it in a functional React component called Searchbar, as such:
Searchbar.js
import axios from "axios"
async function getRepos() {
const response = await axios({
method: "GET",
url: "/api/repositories",
});
return response.data;
}
function Searchbar() {
const [repos, setRepos] = useState([]);
// Get the repos on load
useEffect(async () => {
setRepos(await getRepos());
}, []);
return (
<div>
{repos.map((repo) => <p>{repo}<p>)}
</div>
);
}
However, when I run npm run start and run the development server, all of my API requests are going to http://localhost:3000/api/repositories, which obviously returns a 404 error. What am I doing wrong?

setupProxy.js in Create React App not working

Hello I am trying to get a dynamic proxy going in react and express. I do not want to configure the proxy in the package.json because I need it to be dynamic. I have tried the following using setupProxy.js by the CRA documentation. Here is my code
TypeError: Cannot read property 'split' of null
[1] at required (/Users/chadlew/Desktop/SC.CRM.React/client/node_modules/requires-port/index.js:13:23)
[1] at Object.common.setupOutgoing (/Users/chadlew/Desktop/SC.CRM.React/client/node_modules/http-proxy/lib/http-proxy/common.js:101:7)
[1] at Array.stream (/Users/chadlew/Desktop/SC.CRM.React/client/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js:127:14)
[1] at ProxyServer.<anonymous> (/Users/chadlew/Desktop/SC.CRM.React/client/node_modules/http-proxy/lib/http-proxy/index.js:81:21)
[1] at HttpProxyMiddleware.middleware (/Users/chadlew/Desktop/SC.CRM.React/client/node_modules/http-proxy-middleware/dist/http-proxy-middleware.js:22:32)
This is the error I'm getting everytime.
And here is my code: setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api', // You can pass in an array too eg. ['/api', '/another/path']
createProxyMiddleware({
target: process.env.REACT_APP_PROXY_HOST,
changeOrigin: true,
})
);
};
Here is the React:
import React, { useState, useEffect } from 'react'
import GoogleLogin from 'react-google-login';
const Login = ({history}) => {
const [authData, setAuthData] = useState({});
useEffect(() => {
if(Object.keys(authData).length > 0) {
(async () => {
const res = await fetch("/api/auth/login", {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(authData)
});
// This data would be set into app level state (react-context api) and be accessible everywhere
const { message, isAuth, userData } = await res.json();
})();
}
}, [authData, history])
const successHandler = data => {
setAuthData(data);
history.push("/home");
}
const failureHandler = (data) => setAuthData(data);
return (
<div className = "login-page">
<h1 style = {{marginBottom: '1rem'}}>Welcome</h1>
<GoogleLogin
clientId = {process.env.REACT_APP_GOOGLE_CLIENT_ID}
buttonText = "Login with Google"
onSuccess = {successHandler}
onFailure = {failureHandler}
cookiePolicy = {'single_host_origin'}
/>
</div>
)
}
export default Login;
Whenever I login with google I get the error message and the proxy ultimately does not work. Any suggestions would be highly appreciated

How to use http-proxy-middleware with react and passport.js

Well,I am working on a react app.I have an express server at localhost:5000 and the react app on localhost:3000.I am going through the google oauth flow using passportjs.Now the real problem is I have used the http-proxy-middleware to go to localhost:5000/auth/google from my react app using the log in button which directs to /auth/google.Then after authenticating I should be returned to the callbackURL which is /auth/google/callback.then from here i should be redirected to localhost:3000/surveys but I am getting redirected to localhost:5000/surveys which does not exist.So i am getting error:can not get /surveys.But when i log out using the logout button which directs to /api/logout then i am getting redirected to the homepage at '/' which is at localhost:3000.So why am i getting redirected to localhost:3000/ and not localhost:5000/ in this case.And how can i go to localhost:3000/surveys instead of localhost:5000/surveys as mentioned in the beginning?
//passport js file
const passport = require("passport");
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const mongoose = require("mongoose");
const keys = require("../config/keys");
const User = mongoose.model("users");
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id).then((user) => {
done(null, user);
});
});
passport.use(
new GoogleStrategy(
{
clientID: keys.googleClientID,
clientSecret: keys.googleClientSecret,
callbackURL: "/auth/google/callback",
proxy: true,
},
async (accessToken, refreshToken, profile, done) => {
const existingUser = await User.findOne({ googleId: profile.id });
if (existingUser) {
return done(null, existingUser);
}
const user = await new User({ googleId: profile.id }).save();
done(null, user);
}
)
);
//the routes for my express server
const passport = require("passport");
module.exports = (app) => {
app.get(
"/auth/google",
passport.authenticate("google", { scope: ["profile", "email"] })
);
app.get(
"/auth/google/callback",
passport.authenticate("google"),
(req, res) => {
res.redirect("/surveys");
}
);
app.get("/api/current", (req, res) => {
res.send(req.user);
});
app.get("/api/logout", (req, res) => {
req.logout();
res.redirect("/");
});
};
//the proxy setup in react src folder
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
"/auth/google",
createProxyMiddleware({
target: "http://localhost:5000",
changeOrigin: true,
})
);
app.use(
"/api",
createProxyMiddleware({
target: "http://localhost:5000",
changeOrigin: true,
})
);
};
//my react header component
import React from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
class Header extends React.Component {
renderContent() {
switch (this.props.auth) {
case null:
return;
case false:
return (
<li>
Log In
</li>
);
default:
return (
<li>
Log Out
</li>
);
}
}
render() {
return (
<nav>
<div className="nav-wrapper">
<Link to={this.props.auth ? "/surveys" : "/"} className="brand-logo">
Emaily
</Link>
<ul className="right">{this.renderContent()}</ul>
</div>
</nav>
);
}
}
const mapStateToProps = (state) => {
return { auth: state.auth };
};
export default connect(mapStateToProps)(Header);
Well,just removing the change origin from proxy did the work!

http-proxy-middleware does't catch request from react app to API

Into my component
axios.post('/api/' + 'create', {
name: 'new name'
},
{
headers:
{
'Content-Type': 'application/json'
}
}
)
into setupProxy.js , created from third part official instruction https://facebook.github.io/create-react-app/docs/proxying-api-requests-in-development
const proxy = require('http-proxy-middleware');
module.exports = function (app) {
app.use(proxy('/api/', {
target: 'http://my-api.com/',
changeOrigin: true
}));
};
When i call method with axios from my app
into browser console write
POST http://localhost:3000/api/create 404 (Not Found)
I tryed to write /api/* and /api/** into configuration http-proxy-middleware , but it did't help me.
What it does't work?
Please try using below code, with http-proxy-middleware version 1.0.0 onwards, you cannot use proxy as the name.
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = (app) => {
app.use(createProxyMiddleware('/api',
{ target: 'http://localhost:3001/'
}));
}
Note: found this from one of the PR discussions here: https://github.com/facebook/create-react-app/issues/8550
I know its late and I came across the same issue. Keeping what worked for me so that others can give it a try.
I proxied this endpoint - https://services.odata.org/V2/Northwind/Northwind.svc/Customers?$format=json
setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = (app) => {
app.use(createProxyMiddleware('/api2', {
target: 'https://services.odata.org/V2/Northwind/Northwind.svc/',
changeOrigin: true,
pathRewrite: { '^/api2': '' }
})
);
}
Your .js file
triggerCORSCall() {
axios.get(`/api2/Customers?$format=json`)
.then(response => {
alert('Success');
}).catch(error => {
alert('Failure');
console.log(error);
})
}

Resources