I'm using the asyncData with axios to get a local.json file from my static folder. I just want to get it locally for the moment as i've added all my methods as i'm waiting for my API to be built.
To use async I need the full path and URL so I need an env variable, however I keep getting a 403 on my server or I get a random error. I need the path to be whatever the URL is hosted on in my axios call.
The URL needs to be dynamic because I'm using gitlab CI and the URL changes depending what branch i'm on, so I can't set a Dev, Prod URL
If I replace context.env.baseUrl with my localIP it works but I need the URL to be "my hosted URL". I need this to be a variable as i'm using gitlab with different URL's
Async Data
asyncData(context) {
return axios.get(context.env.baseUrl+'/products.json')
.then(response => {
return {
servers: response.data.products
}
})
.catch(e => context.error(e))
}
nuxt.config.js
env: {
// The baseUrl needs to be dynamic - whatever the server is on
baseUrl: process.env.BASE_URL || 'http://localhost:3000'
}
If you want to use static file present in same project then just import/require it instead of using axios. See example below
<script>
export default {
asyncData() {
const servers = require('#/static/local.json')
return {
servers
}
}
}
</script>
You can create an axois instance and set a base URL to avoid the headache.
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
});
See: https://github.com/axios/axios#axioscreateconfig
One of many ways that I know and the easiest is using axios module for nuxt. Many of the axios config pain points are addressed via this module instead of using standalone axios package.
Then in your nuxt.config.js
Add this like so
axios: {
baseURL: () => {
if (process.env.NODE_ENV !== "production") {
return 'localhost:5000/api/';
}
return https://www.example.com/api/;
}
}
USAGE IN NUXT PAGES
async asyncData({ $axios }) {
try {
let response = await $axios.get("/your-api-route");
return response;
} catch (err) {
console.log(err);
}
}
Related
I am building out a webpage which needs to make a call to the Google Geocoder api.
In order to hide the api key from public view, I am trying to set up server middleware to act as a REST api endpoint.
I have checked through all of the documentation and copied all of it, but the response is always the same. I receive the entirety of the html body back from the axios request rather than anything else I send back via express.
In my component I have the following code:
computed: {
normalizedAddress() {
return `${this.member.address.street} ${this.member.address.city}, ${this.member.address.state} ${this.member.address.zip}`.replace(
/\s/g,
'+'
)
}
},
methods: {
async getLocation() {
try {
const res = await axios.get(
`/api/geocode/${this.normalizedAddress}`
)
console.log(res)
} catch (err) {
console.log(err)
}
}
},
In nuxt.config.js I have this setup
serverMiddleware: ['~/api/geocode.js'],
In the root of my project I have an api folder with geocode.js stored there.
geocode.js is below
import express from 'express';
import axios from "axios";
let GEO_API = "MY_API_KEY"
const app = express();
app.use(express.json());
app.get("/", async (req, res) => {
const uri = `https://maps.googleapis.com/maps/api/geocode/json?address=${req.params.address}&key=${GEO_API}`
try {
const code = await axios.get(uri);
if (code.status !== "OK") {
return res.status(500).send(code.status)
}
return res.status(200).send(code);
} catch (err) {
return res.status(500).send(err);
}
});
export default {
path: "/api/geocode/:address",
handler: app
}
Again. The response always has the entire html document from the website sent back (some 100 pages of code).
Even when I set the response to fixed text, that is not sent.
The only detail I can think of that might be interrupting it is that I have my own custom routing setup using the #nuxtjs/router build module in use.
I have a very basic nuxt.js application using JSON in a local db.json file, for some reason the generated static site links leading to network error, but I can access them from the url or page refresh.
nuxt config
generate: {
routes () {
return axios.get('http://localhost:3000/projects')
.then((res) => {
return res.data.map((project) => {
return '/project/' + project.id
})
})
}
},
main root index page
data() {
return {
projects: []
}
},
async asyncData({$axios}){
let projects = await $axios.$get('http://localhost:3000/projects')
return {projects}
}
single project page
data() {
return {
id: this.$route.params.id
}
},
async asyncData({params, $axios}){
let project = await $axios.$get(`http://localhost:3000/projects/${params.id}`)
return {project}
}
P.S. I have edited the post with the code for the main and single project page
Issues with server-side requests of your application are caused by conflicts of ports on which app and json-server are running.
By default, both nuxt.js and json-server run on localhost:3000 and requests inside asyncData of the app sometimes do not reach correct endpoint to fetch projects.
Please, check fixed branch of your project's fork.
To ensure issue is easily debuggable, it is important to separate ports of API mock server and app itself for dev, generate and start commands.
Note updated lines in nuxt.config.js:
const baseURL = process.env.API_BASE_URL || 'http://localhost:3000'
export default {
server: {
port: 3001,
host: '0.0.0.0'
},
modules: [
['#nuxtjs/axios', {
baseURL
}]
],
generate: {
async routes () {
return axios.get(`${baseURL}/projects`)
.then((res) => {
return res.data.map((project) => {
return '/project/' + project.id
})
})
}
}
}
This ensures that API configuration is set from a single source and, ideally, comes from environmental variable API_BASE_URL.
Also, app's default port has been changed to 3001, to avoid conflict with json-server.
asyncData hooks have been updated accordingly to pass only necessary path for a request. Also, try..catch blocks are pretty much required for asyncData and fetch hooks, to handle error correctly and access error specifics.
I am using the rest api to get the data. For that i am giving the hardcoded url. How to remove this one?
Here is service.ts :-
getAllEmployees(): Observable<Employee[]>{
return this._httpService.get("http://localhost:8080/EmpProject/getAllEmployees")
.map((response: Response) => response.json())
.catch(this.handleError);
}
I wan to remove this http://localhost:8080 hardcode value.
You need to use environments.
https://angular.io/guide/build
You can use the environment files for this.
For development environment add your URL to the file environment.ts. You can find it in src > environments.
export const environment = {
production: false,
baseUrl: 'http://localhost:8080'
};
You can use it like this
import { environment } from '../../environments/environment';
#Injectable()
export class MyService {
constructor(private httpClient: HttpClient) { }
getData(id: number) {
let url = environment.baseUrl + '/datas/1';
return this.httpClient.get<JSON>(url);
}
}
The same thing for production environment, but you need to change the file environment.prod.ts
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 have axios module in my Nuxt.js project.
I also set up my baseUrl (for API) in localhost:4040/api while my client is running on port 3000.
When I fetch image data in the API, it returns a relative path to the api server which is like '/upload/1.png'
{
"src":"/upload/1.png"
}
So, I need to get the axios baseUrl and concat it with it to make full path to the image.
Is there any way to do it other than hardcoding it?
If in nuxt.config.js you defined:
axios: {
baseURL:"localhost:4040/api/"
}
All you need to do for the image is to point to it as follows:
:src="`${$axios.defaults.baseURL}upload/1.png`"
You can access axios config like this to get your api base URL:
this.$axios.defaults.baseURL
In case if someone is wondering how to make an axios baseURL domain-independent:
Here is how simply it can be achieved:
axios: {
baseURL: '/'
}
It will work on localhost:3000/api as well as on any-domain.com/api
I had a similar problem.
My resolution step is as follows:
Delete folder .nuxt + remove cache in browser
Changer
axios: {
baseURL: 'http: // localhost: 8080/api'
}
It works as expected. Before that, I tried a lot of ways like community tutorials but not effective.
I had nuxt.config.js like this:
axios: {
baseURL: "http://localhost:8000/api/",
},
in one of my components, I made an api call which responded like:
eachpost: {
....
user: {
....,
avatar: 'users/default.png'
}
}
here avatar object has a relative path to my image, but in the client side, I must have the absolute path to the server.
so I wrote the below code in my component which worked successfully.
My absolute path to the photo was: http://localhost:8000/storage/users/default.png
<img :src="`${$axios.defaults.baseURL.slice(0,22)}storage/${eachPost.user.avatar}`" :alt="`${eachPost.user.name}`">
You just append window.location.origin with your axios url
you can set base url for axios
axios.defaults.baseURL = 'https://api.example.com/';
so next time this url will be add with your required path for calling api
for details you can see from below link
https://github.com/axios/axios
If someone intends to call axios, call it via dispatch store/index.js
export const actions = {
// nuxt server Init only works on store/index.js
async nuxtServerInit ({dispatch}) {
let response = await dispatch ('member / list', {page: 1});
console.log (response);
}
}
module file member.js
async list ({commit}, payload) {
return await this. $ axios. $ post ('/ user / list', payload) .then ((response) => {
commit ('fetchSuccess', response);
return response;
})
.catch (error => {
return error.response.data;
});
},
file nuxt.config.js config with axios api
axios: {
baseURL: 'http://localhost:9020/api'
},
Sorry if the answer is not appropriate but someone will need to hope that this explains them