http-fake-backend icon indicating copy to clipboard operation
http-fake-backend copied to clipboard

feature: Support for query parameters

Open boochamoocha opened this issue 8 years ago • 8 comments

Hi. Thows error when url like this

module.exports = SetupEndpoint({
    name: 'v1',
    urls: [{
        params: '/read?cmd=on-enter&pid=1414-414-567-3636',
        requests: [{
            method: 'GET',
            response: '/json-templates/anotherExample.json'
        }]
    }]
    }]
});

boochamoocha avatar Dec 30 '16 07:12 boochamoocha

Nope. This doesn’t work because hapi, the underlying server framework, handles path parameters different to query parameters. They are not part of the route.

We never needed different responses based on query params. So they aren’t configurable for the fake backend for now. The fake backend is pretty stupid and we don’t care if different query params deliver the same response.

Must say that I’m not sure about adding support for them. I would add support if

  • more than one person really needs it
  • it won’t add too much complexity to the code base

Just in case

Regarding your example I could imagine to configure the query params like that:

module.exports = SetupEndpoint({
    name: 'v1',
    urls: [{
        params: '/read',
        requests: [{
            method: 'GET',
            response: '/json-templates/anotherExample.json',
            query: {
                cmd: 'on-enter',
                pid: '1414-414-567-3636'
            }
        }]
    }]
});

I’m not sure about the expected behavior. Should it be analogous to the behavior of path params?

That means: http://localhost:8081/api/v1/read?cmd=on-enter&pid=1414-414-567-3636 would be the only successful url whereas the following examples would generate 404 errors:

More flexibility

So I guess query params should have the same flexibility like path parameters:

module.exports = SetupEndpoint({
    name: 'v1',
    urls: [{
        params: '/read',
        requests: [{
            method: 'GET',
            response: '/json-templates/anotherExample.json',
            query: {
                cmd: '{cmd}',
                pid: '{pid?}'
            }
        }]
    }]
});

That means: http://localhost:8081/api/v1/read would still generate a 404 error whereas the following would be valid urls returning the response:

mischah avatar Dec 30 '16 13:12 mischah

Hey mischah!

We need support for query parameters! 🙂 It would be very useful if you implement what you have proposed.

Many thanks in Advance, Anuj

anujshankar avatar Apr 11 '17 09:04 anujshankar

Hi Mischah,

I am using your project to mock backend and focus on my frontend work. Can you please implement query parameters in the urls if you get some time?

Thank you, Jeevan

noobg1 avatar Apr 13 '17 04:04 noobg1

Hej @noobg1 @anujshankar @boochamoocha,

challenge accepted. I just pushed a refactoring to master which hopefully improves maintainability and is a good start for adding this feature.

Can’t promise anything right now because of a constraint I mentioned before: I don’t want to add too much bloat the code base to implement a feature we (the project owners) don’t need.

… but I’m going to tackle this within the next couple of days.

Cheers, Michael

mischah avatar Apr 13 '17 21:04 mischah

Thanks @mischah! Looking forward and excited about this.

anujshankar avatar Apr 14 '17 14:04 anujshankar

Hey Michael!

We have our own implementation of handling query params for http-fake-server.

Details of the implementation:

  1. Created a mapURLs file which maps the APIs to the respective JSON responses.
  2. Checking if any query params were present in the query and if it endpoint matches in the hash map then we return the JSON response as mentioned in the hash map.

So basically if a user needs to handle query params then he/she just has to:

  1. Create route till the path params.
  2. Create a entry in the mapURLs file with the ‘endpoint(with query params): json file’

Example:

Contents of mapURLs.js

const urlMaps = {
    '/api/offer/{number}?filteredby=abc’: '/json-templates/abc.json',
    '/api/offer/{number}?filteredby=xyz’: '/json-templates/xyz.json'
};

Changes in the setup.js

const createRoutes = function (url) {

            const params = url.params || '';

            url.requests.forEach((proposedRequest) => {

                const method = proposedRequest.method || 'GET';
                const supportedMethod = {
                    method,
                    path: path + params,
                    handler: function (request, reply) {

// Added logic for picking up the mapped urls for understanding query parameters
                        let response, mapPath = path + params + '?';
                        const obj = request.query;

                        if (Object.keys(obj).length !== 0) {
                            Object.keys(obj).forEach((key) => {
                                mapPath += key + '=' + obj[key] + '&';
                            });
                            mapPath = mapPath.slice(0, -1);
                        }
                        console.log(mapPath, mapUrls.hasOwnProperty(mapPath));

                        if ( mapUrls.hasOwnProperty(mapPath)) {
                            response = require('../../..' + mapUrls[mapPath]);
                            console.log('resp');
                            return reply(response);
                        }
// End
                        else if (proposedRequest.statusCode && !proposedRequest.response) {
                            response = Boom.create(proposedRequest.statusCode);
                        }
                        else if (settings.statusCode && !proposedRequest.statusCode) {
                            response = Boom.create(settings.statusCode);
                        }
                        else {
                            server.log('info', 'Received payload:' + JSON.stringify(request.payload));

                            if (typeof proposedRequest.response === 'string') {
                                response = require('../../..' + proposedRequest.response);
                            }
                            else {
                                response = proposedRequest.response;
                            }

                        }

                        if (proposedRequest.statusCode && proposedRequest.response) {
                            return reply(response).code(proposedRequest.statusCode);
                        }
                        return reply(response);
                    }
                };
                routes.push(supportedMethod);
            });

Any suggestions to improve this approach?

Thanks, Anuj Shankar

anujshankar avatar Apr 17 '17 06:04 anujshankar

Any news? I wasn't able to get the version of @anujshankar up and running... :-/

JanLoebel avatar Feb 28 '18 22:02 JanLoebel

The only news is, that this one isn’t on the top of my priority list. Just because we still don’t need this feature. Therefore I wont make any promises about implementing it.

But I'm open for a PR :octocat:

Sorry for the folks needing this 😕

Cheers, Michael

mischah avatar Mar 01 '18 14:03 mischah