I have a small front-end and back-end separated project with development environment and production environment, so I want to set the proxy to call api. vue/cli version is 4.6.5.
file structs:
src
axios
api.js
request.js
components
home
LastBlogs.vue
.env.development
.env.production
package.json
vue.config.js
.env.development:
NODE_ENV = 'development'
VUE_APP_BASE_API = '/dev-api'
VUE_APP_API_ADDRESS= 'http://localhost:8080/blog/'
.env.production:
NODE_ENV = 'production'
# base api
VUE_APP_BASE_API = '/api'
# api publicPath
VUE_APP_API_ADDRESS= 'http://localhost:8080/blog'
vue.config.js:
'use strict'
var path = require('path')
module.exports = {
configureWebpack: {
devtool: 'source-map'
},
assetsDir: 'static',
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 8001,
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: [process.env.VUE_APP_API_ADDRESS], // api地址
changeOrigin: true,
ws: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: '/api',
}
}
}
}
}
axios:
import axios from 'axios'
import qs from 'qs'
// import {app} from '../main.js'
console.log(process.env)
/****** 创建axios实例 ******/
const request = axios.create({
baseURL: process.env.VUE_APP_API_ADDRESS,
timeout:5000
})
// some code of interceptors
export default request;
api.js:
import request from './request.js'
var api = process.env.VUE_APP_BASE_API //'/api'
export function getLastBlogs(){
return request({
url: api+'/blog/lastBlogs',
method: 'get'
})
}
I call api in vue file as this:
<script>
import {getLastBlogs} from '#/axios/blogApi.js'
export default {
name: 'LastBlogs',
data() {
return {
blogs: ["AAAA", "BBBB"]
}
},
created: async function(){
let res = await getLastBlogs();
this.blogs = res.data
}
}
</script>
I got 404 at terminal:
error: xhr.js:160 GET http://localhost:8080/blog/dev-api/blog/lastBlogs 404
and the api of back end is ok:
When I put http://localhost:8080/blog/api/blog/lastBlogs in browser, I get this:
{"code":"0","msg":"操作成功","data":[{"id":1,"blogUser":1,"blogTitle":"test1","blogDescription":"for test","blogContent":"ABABABABAB","blogCreated":"2020-09-20T10:44:01","blogStatus":0},{"id":2,"blogUser":1,"blogTitle":"test2","blogDescription":"for test","blogContent":"BABABABABA","blogCreated":"2020-08-20T10:44:01","blogStatus":0}]}
What should I do? Thanks.
So you are configuring Vue CLI dev-server (running on port 8001) to proxy all requests to /api to http://localhost:8080/blog/api (server) but at the same time configure Axios to use baseURL: process.env.VUE_APP_API_ADDRESS ...which means Axios is sending all requests directly to your server instead of proxy...
Just remove that baseURL: process.env.VUE_APP_API_ADDRESS from Axios config
I also believe your pathRewrite option in proxy config is incorrect.
You dispatch request to /dev-api/blog/lastBlogs
Request goes to Vue dev-server (localhost:8001)
Proxy translates /dev-api into http://localhost:8080/blog/dev-api = http://localhost:8080/blog/dev-api/blog/lastBlogs
pathRewrite is applied to whole path part of the URL - /blog/dev-api/blog/lastBlogs - RegEx ^/dev-api will not match
Try to change pathRewrite into [process.env.VUE_APP_BASE_API]: '/api'
Related
I think this problem follows this one on netlify API from proxy not working after deploying on netlify
I am setting up a Vite app and making an axios api request in my app component
getSuggestionList(street, zip, city) {
this.axios.get('/1.0/address/find?country=at&zip=' + zip + '&city=' + city + '&street-address=' + street + '&street-number=&offset=1&limit=100', {
auth: {
username: '7166-631A-5394-4C03-9106-0A93-C433-2613',
password: ''
}
})
Now, for development I configured a proxy in server
in vite.config.js
import { fileURLToPath, URL } from "url";
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
server: {
proxy: {
'/1.0/address': 'http://api.opendata.host/'
}
},
proxy: {
'/1.0/address': {
target: 'http://api.opendata.host/',
changeOrigin: true,
secure: false,
ws: true,
}
}
});
Following this guide
https://rubenr.dev/en/cors-vite-vue/
I understand this does not transfer to production, so I also tried the proxy part. I don't get a response, just like described in the netlify guide.
From Heroku docs
https://github.com/heroku/heroku-buildpack-static
I have the basic setup without proxies (leading to the initial, no-response behavior)
in static.json:
{
"root": "./dist",
"clean_urls": true,
"routes": {
"/**": "index.html"
},
"proxies": {
"/1.0/address": {
"origin": "http://api.opendata.host/"
}
}
}
And when I add proxies I get a 404 not found. When I change up the spelling: no response again, so it seems to be making a connection with the proxies configuration. But why not they way it works locally? Does anyone see my error here or having something for me to try?
I found it: for anyone else having trouble with this kind of deployment on Heroku -- the mountpoint "/1.0/address" in static.json seems to be replaced resulting in the 404 not found.
For production I added a prefix /api in my axios call, something like
var apiPath = '/1.0/address/find?country=at&zip=' + zip + '&city=' + city + '&street-address=' + street + '&street-number=&offset=1&limit=100'
var prodMountpoint = '/api' // /api/
if (import.meta.env.PROD) {
apiPath = prodMountpoint + apiPath
}
This results in a correct api call: "/api" is replaced with the proxied host, if I understand correctly. For development, the vite.config.js does its work as before.
I'm using the following configuration in my vue.config.js located in the root of my repository and it's not working.
module.exports = {
devServer: {
proxy: "http://localhost:3030"
}
}
and this is how I'm trying to call it
return await fetch("/posts", options).then((response) =>
response.json()
).catch(e => console.log("Error fetching posts", e));
however when I change the calling code to the code shown below everything works
return await fetch("http://localhost:3030/posts", options).then((response) =>
response.json()
).catch(e => console.log("Error fetching posts", e));
Edit:
I should have mentioned that I'm using Vite for builds as that was causing some other problems for me with environment variables so it's possible they are causing problems with proxies too.
I looked into this more and it turns out that Vite does have proxy features and so I tried updating my code to use their proxy with still no luck.
// vite.config.js
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
"/posts": "http://localhost:3030/posts"
}
})
vue.config.js is intended for Vue CLI scaffolded projects (and your config would've worked there), not for Vite projects. Vite's configuration is stored in vite.config.js.
Your Vite config value for server.proxy contains an unnecessary /posts suffix:
"/posts": "http://localhost:3030/posts"
^^^^^^
The value should just be the base URL to which the original path is appended:
"/posts": "http://localhost:3030"
Example:
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
server: {
proxy: {
'/posts': 'http://localhost:3030'
}
}
})
GitHub demo
I cannot seem to get the devServer: proxy setting working in my vue / express app.
My vue.config.js file is in the root of my client folder and looks like:
module.exports = {
devServer: {
proxy: {
'api': {
target: 'http://localhost:5000'
}
}
},
transpileDependencies: [
'vuetify'
]
}
I'm sending a request from the frontend using axios like this:
const response = await http.get("/api/auth/authenticate");
My express app is running on localhost:5000 and I've configured endpoints as such:
...other endpoints
app.use("/api/auth", authController);
The request appears in my network tab as:
Request URL: http://localhost:8080/api/auth/authenticate
and returns a 404 error.
What am I missing here?
Since now it is not fetching from your backend, but searching for some static content (hitting 8080, vue must be running on this port). Try using, so that it get redirected to proxy:
proxy: {
'^/api': {
target: 'http://localhost:5000',
ws: false,
changeOrigin: true
},
Or just '/api' instead of '^/api'
I'm using an API with my Nuxt, here is my nuxt.config.js to allow the requests :
axios: {
prefix: '/api/',
proxy: true,
},
proxy: {
'/api/': {
target: process.env.API_URL || 'http://localhost:1337',
pathRewrite: {
'^/api/': '/',
}
},
}
On a specific page of my app, I need to send requests to another API from another domain. I'm using axios direclty in this Vue component :
axios.post('mysite.com/widget.rest')
As response, I obtain CORS error. Can I allow multiple API in my config ?
If you mean being able to access APIs under different URLs, AFAIK it's not possible out of the box. We tried adding proxy to different targets, but it only worked on client side, not during SSR.
What we ended up doing is having the default axios instance for our main API, and creating a plugin that creates extra axios instances for our other APIs for SSR.
Add extra "suburl" to proxy - this sorts out client side and means no CORS issues.
proxy: {
'/forum/': {
target: 'https://other.domain.com/',
pathRewrite: {'^/forum/': '/'}
},
'/api/': ...
},
For SSR to work, axios should hit directly the other API
import Vue from 'vue'
var axios = require('axios');
const forumAxios = axios.create(process.client ? {
baseURL: "/"
} : {
baseURL: 'https://other.domain.com/'
});
// this helps Webstorm with autocompletion, otherwise should not be needed
Vue.prototype.$forumAxios = forumAxios;
export default function (context, inject) {
if (process.server) {
forumAxios.interceptors.request.use(function (config) {
config.url = config.url.replace("/forum/", "");
return config;
}, function (error) {
return Promise.reject(error);
});
}
inject('forumAxios', forumAxios);
In components, you can then use something like:
async asyncData({app}) {
let x = await app.$forumAxios.get("/forum/blah.json");
You can use process.env prop of course instead of hardcoded URL.
This will hit https://other.domain.com/blah.json.
I am unable to provide axios a baseUrl using an enviroment variable
I am using nuxt/vue/axios
What I have is roughly:
// axios.js
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
axios.defaults.baseURL = process.env.BASE_URL
Vue.use(VueAxios, axios)
and
// index.vue (front page as it appears on the client)
populateFilters () {
Vue.axios.get('filters').then((response) => {
this.$store.commit('data/filters', response.data)
})
.catch((e) => {
console.error(e)
})
}
and inside nuxt.config.js
// nuxt.config.js
build: {
extractCSS: true,
extend (config, ctx) {
// Run ESLint on save
const envLoad = require('dotenv').config()
if (envLoad.error){
throw result.error
}
}
},
console.log(process.env.BASE_URL) prints the correnct connection string in CMD, however, in chrome web browser it outputs "undefined" and I get the following error
GET http://localhost:3000/filters 404 (Not Found)
meaning that axios (probably) defaults to http://localhost:3000 whenever the baseUrl for axios has not been set.
What I think the problem is
The server/client pair that is loaded up by nuxt has different contexts or that the server loads up axios before the enviroment variables have been loaded
What I need
I need to be able to either:
create .env files that contains (amongst other things) the BASE_URL
define these enviroment variables somewhere in the code (nuxt.config.js ?)
Solution
Please see the accepted answer
In addition, install nuxtjs/dotenv
npm install #nuxtjs/dotenv
and make your nuxt.config.js look like:
// nuxt.config.js
require('dotenv').config()
module.exports = {
modules: [
'#nuxtjs/dotenv',
'#nuxtjs/axios',
],
axios: {
baseURL: process.env.BASE_URL
},
}
note that require('dotenv').config() must be at the top
Theres a nuxt axios module you can use. You can declare it in the module sectiont of your nuxt.config.js so you dont need your file axios.js. This is described here https://github.com/nuxt-community/axios-module#usage
By loading it in the modules in the nuxt.config.js file you will have your axios instance accesible with this.$axios in your components.
You can declare the base url in the nuxt.config.js
modules: [
// Doc: https://github.com/nuxt-community/axios-module#usage
['#nuxtjs/axios', {
baseURL: 'http://jsonplaceholder.typicode.com'
}]
],
/*
** Axios module configuration
*/
axios: {
// See https://github.com/nuxt-community/axios-module#options
},
For "other environement variables" you can use the vuex store to have them available to all components.