0

I started a simple Vue project and faced the first problems with static data. I have a json file tours.json which keeps getting a 404 Error through axios GET request.

    <script>
    import axios from 'axios';
    const tours = 'http://localhost:8080/server/tours.json';
    export default {
        name: "TourInformations",
        data() {
            return {
                tourInformations: ''
            };
        },
        methods: {},
        created() {
            axios.get(tours).then(res => {
                console.log(res);
            }).catch(err => console.log(err))

        }  
    };
    </script>

First things I tried were changing the path to my json file. Didn't help. I tried to use relative paths, to use localhost:8080 with and without http:// respecitve https://.

The console keeps saying:

GET http://localhost:8080/server/tours.json 404 (Not Found)

Error: Request failed with status code 404
    at createError (createError.js?2d83:16)
    at settle (settle.js?467f:17)
    at XMLHttpRequest.handleLoad (xhr.js?b50d:59)

Thanks for every help!

Edit: What's weird is that I get a response when I use an external API like jsonplaceholder or others with the same code. Why is this? Changing my address to https:// shows a CORS error. I don't think I'm with CORS on a better way. I'm confused. Especially as a beginner I cannot understand why a simple path to a local JSON file doesn't work, but a path to a secure external API does.

Edit2: Putting my /server/tours.json into the public folder works for now. The data is shown in the console. This is now where my json file is stored: 'http://localhost:8080/public/server/tours.json. All fine here.

But when I move my json file into every other folder and changing my route accordingly. It doesn't matter how I try to adapt my route to the new place of my json file, it keeps showing 404 error. For example: If I move /server/tours.json into my src directory, change my axios path from http://localhost:8080/server/tours.json to http://localhost:8080/src/server/tours.json it shows 404 (GET http://localhost:8080/src/server/tours.json 404 (Not Found)). The route to my file should be correct like this. A 404 appears also with a relative path like ../server/tours.json. (My axios code from above is placed in on of my components where I am changing my path depending of the location of my json.

Here's my (simplified) file structure:

    root
    ├── public
    ├────── favicon.ico
    ├────── index.html
    ├────── server
    ├──────────tours.json
    ├── src
    ├────── assets
    ├────── components
    ├───────── Tours.vue ###My axios code in here
    ├──────────── ...
    ├────── App.vue
    ├────── main.js
    ...

The route http://localhost:8080/public/server/tours.json with the file structure above works. Okay.

And here is the file structure and route which shows a 404 Error. http://localhost:8080/src/server/tours.json

    root
    ├── public
    ├────── favicon.ico
    ├────── index.html
    ├── src
    ├───────server
    ├──────────tours.json
    ├────── assets
    ├────── components
    ├───────── Tours.vue ###My axios code in here
    ├──────────── ...
    ├────── App.vue
    ├────── main.js
    ...

So the json in public works, an external API works to. The axios snippet is correct. It's about the ropute right? I tried (feels like) every possible route which could cause the issue. I'm confused.

What I miss? This topic should be much much shorter. So, there's something I miss here. Otherwise I cannot explain why something simple like a proper file route seems to be so confusing.

It's obviously not the route which is wrong. Even if I move my json to my root and change my path into http://localhost:8080/tours.json it shows a 404.

2
  • Is localhost:8080 the address of your Vue development server or is it some other server? Where, relative to your Vue files, have you put the file tours.json on your file-system? What happens if you just open the URL directly in a web browser, just typing the URL directly into the address bar? Until you can get that working there's no way you'll be able to write suitable code to retrieve it from the UI. On the face of it the problem just appears to be that there's a mismatch between the location of the file on your file-system and the URL you're using to access it. Commented Nov 20, 2019 at 0:08
  • It's the address of my Vue development server. My tours.json is outside of the src in a seperate server folder. If I enter the URL into my browser, it brings me to my Vue app like normal. Commented Nov 20, 2019 at 9:43

3 Answers 3

4

I think the problem is simply that you've put the file in the wrong place on your file-system.

Assuming you're using Vue CLI and you want the URL:

http://localhost:8080/server/tours.json

then you should place the file at the path:

project-root/public/server/tours.json

For reference, index.html will typically be at the path:

project-root/public/index.html

Official documentation:

https://cli.vuejs.org/guide/html-and-static-assets.html#static-assets-handling

There are other ways to achieve a similar effect using custom configuration of the server but dropping static assets into the public folder should work out-of-the-box.

Update:

Based on your comments and the updated question I'm going to try to explain further.

Firstly, completely ignore the axios part here. As you've suggested in the question that isn't the problem. You can replicate exactly the same behaviour by typing these URLs directly into your browser address bar, you'll get a 404 just the same as you are with axios.

The underlying problem here seems to be that you believe that there's a direct correspondence between the file structure within your project's root folder and the 'routes', or URL paths. This is not the case. They are two separate things.

Let's consider for a moment what happens when you make a request to a web server. Not necessarily the Vue development server, any web server.

When you make a request to a web server it is entirely at that server's discretion to decide what to send back. So a request to http://localhost:8080/server/tours.json involves contacting the server at localhost:8080 and asking it for server/tours.json.

On the face of it that might appear to be asking for the file tours.json from the folder server. However, that is not necessarily the case. It is up to the server to decide what server/tours.json means and what the response should be. Not only does the response not have to the contents of a file but it doesn't even have to be static. The server could generate a response on-the-fly, maybe based on the result of a database query.

It is really important to understand this. Sending a request of http://localhost:8080/server/tours.json does not necessarily mean 'give me the file tours.json from the folder server'. It is entirely at the server's discretion to decide what to return.

Now, it is common for a web server to have to handle static assets. The easiest way to store such assets is as files. Rather than configuring individual mappings between URL paths and file-system paths it is generally easier to organise the files in a folder structure that maps conveniently onto the URL paths. Typically the web server would be configured to treat a particular folder as the 'root' for static assets and then all the folders/files within that root would be served up using matching URL paths.

In general, the exact mechanism for configuring this would depend on which web server you're using. Of course we're specifically interested in the Vue development server, so let's get back to considering that particular server.

There is a lot of stuff going on behind the scenes with the Vue development server. It is not simply serving up files from the file-system.

The contents of the src folder require a build. They won't be served up as-is to the browser. The server won't treat them as static assets. If you try to access http://localhost:8080/src/App.vue you'll find you get a 404 response. That is to be expected.

Instead the server will go through the contents of the src folder and generate the 'files' that it needs. For example it'll pull apart all the .js and .vue files and use them to create one big app.js containing everything. If you look in the Network tab of your browser's developer tools you should see the 'file' app.js being loaded. But this 'file' doesn't actually exist, it is generated dynamically based on the contents of the files in the src folder.

However, it is common for a Vue project to need some static assets. A default CLI project will have an index.html and favicon.ico. These don't need to be generated dynamically so it is convenient just to store them as files on the file-system. The Vue server has a special folder, called public, for holding such files. As discussed earlier, any folders/files within that folder will be mapped directly onto equivalent URL paths (what the question calls routes). The folder public is treated as the root folder for these mappings. So a file located on the file-system at project-root/public/server/tours.json will be mapped onto the URL path server/tours.json, in full http://localhost:8080/server/tours.json. The 'route' is relative to the public folder, not relative to the project's root folder.

While that covers the most important details there are a couple of other things I would note for the sake of completeness.

Firstly, strictly speaking the contents of the public folder are not all static. For the file index.html there's some Webpack magic goes on to inject various things within the page. This is described here but it isn't something worth dwelling on when it comes to understanding how to serve up a simple .json file.

Secondly, it is also possible to include static assets within the src folder, but only in specific cases. For example, the default Vue CLI project creates a file at src/assets/logo.png. However, there is yet more Webpack magic going on here. Once this has been through the build it will have a URL something like http://localhost:8080/img/logo.82b9c7a5.png. Note that this is significantly different from the original path on the file-system. Webpack will trawl through your .js and .vue files and try to update any relative paths that access src/assets/logo.png to point them at the generated path instead. I'm not going to go into detail about precisely how that works here as I don't think it is relevant to the original question. Just be aware that there are limits on when it will work, it isn't actually magic.

There is a somewhat equivalent way of accessing a .json file in the src folder but it doesn't generate a 'route' at all. If you place a .json file somewhere within your src folder then you can import it using import just like you would a .js or .vue file:

import tours from '../server/tours.json'

It is important to appreciate that this is not making a separate AJAX request to the server to load the file. Instead this is telling Webpack to bundle the contents of tours.json into app.js during the build. No 'route' will be created for tours.json if you include it this way.

I'll now go through a couple of the specific remarks in the question to try to clarify where misunderstandings appear to be lurking.

Putting my /server/tours.json into the public folder works for now. The data is shown in the console. This is now where my json file is stored: http://localhost:8080/public/server/tours.json. All fine here.

If you put the file at public/server/tours.json on your file-system then it will be mapped to a URL of http://localhost:8080/server/tours.json. The public will be dropped as it is considered to be the root when it comes to serving up static files.

In the quote above you have claimed that the file is stored at http://localhost:8080/public/server/tours.json. I don't believe that is correct. As you noted previously in the comments the URL path will not contain the /public part.

You should be able to test URL paths by typing them directly into your browser's address bar.

If you need to clarify what URL axios is calling then take a look in the Network tab of your browser's developer tools. That will show you the full URL that it requested.

But when I move my json file into every other folder and changing my route accordingly. It doesn't matter how I try to adapt my route to the new place of my json file, it keeps showing 404 error.

The Vue server does not create routes for all files. It only creates routes for files inside the public folder. So if you put your file somewhere outside the public folder there won't be a corresponding route. No amount of tweaking the URL will help, the route does not exist.

For example: If I move /server/tours.json into my src directory, change my axios path from http://localhost:8080/server/tours.json to http://localhost:8080/src/server/tours.json it shows 404 (GET http://localhost:8080/src/server/tours.json 404 (Not Found)). The route to my file should be correct like this.

Afraid not.

Putting it in the src folder won't have any effect on the available routes. Only putting it in the public folder will cause a route to be created.

You may well have several other files in your src folder. None of these files will be mapped directly onto a route either. If you try to access http://localhost:8080/src/components/Tours.vue you'll get a 404. Instead these files are bundled up into the Webpack build.

If you have the file src/server/tours.json on your file-system then you can access its contents by using import within your .js and .vue files. However, that is all handled by the build process and has nothing to do with creating routes accessible via URLs. That would be a very different process from loading the file via axios.

It's obviously not the route which is wrong. Even if I move my json to my root and change my path into http://localhost:8080/tours.json it shows a 404.

If you want to access a file using the URL http://localhost:8080/tours.json then the correct place to put it on your file-system would be:

project-root/public/tours.json

Recall that the root for serving static files is the public folder. It is not the project's root folder. If you put files outside the public folder then the server will usually just ignore them.

Sign up to request clarification or add additional context in comments.

5 Comments

It works with public, thanks for that! But why is the public ignored by the route? I needed to figure out that, when I added my route like http://localhost:8080/public/server/tours.json it doesnt work but remove the public and make it http://localhost:8080/server/tours.json works fine. I couldn't find an explanation in the docs. But nevertheless, if I put my json file in an other folder it still shows 404. Even though I checked several times if my route my be wrong. Need to find it out. Thanks again for your help!
@DamirLucic You seem to have a false expectation that the server will just serve up all files, no matter where you put them. That isn't how it works. The public folder is special. Files in that folder will be served as 'static assets', using a URL equivalent to the file path within the public folder. If you want to serve up a static file then put it in the public folder, simple as that. If you just put it in some random other folder it'll just be ignored.
I don't expect the server will serve all files no matter where they're placed in. I edited my first post and tried to explain precisely why I'm confused.
@DamirLucic I have added an update to my answer based on your updated question. However, while I have gone into a lot more detail, my answer remains essentially the same.
Thanks for the very detailed explanation. I read it last week, was quite a lot of informations and read it today again to realized that I misunderstood a lot of things about the whole process behind the code. I checked the things you mentioned and indeed, you were right. Before your answer I accepted the fact that I can't just pass an URL like I wanted to and continued to work with importing the file "in the normal way" (like you mentioned too)
1

I have an alternative solution for this kind of problem in .json file

the first thing is to

import projects from '../../static/projects.json' // import this file in your component

declare an empty array in your data

data() {
    return {
        items: []
    }
},

and then create a life-cycle method like created or mounted or etc.

created () {
        let projectData = projects.projects
        return this.items.push(...projectData)
    }

and that's it works just fine without using fetch or axios.

Comments

0

I think the main issue here is you have the .json file but you need a server to actually send back a response to your GET http request, in this response you will have the json data.

In summary, axios creates an http request, in this case a GET request, and you need another software to respond to this http protocol, this response will contain json data, headers, etc.

I would recommend looking into something like express framework for this.

1 Comment

I'm not sure what do you mean. Could you give me an example please? As I understand it correctly, my axios code should at least give back a response in my console with the correct json data. But the file isn't shown. A external API is shown with the same code snippet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.