New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to 'get' data using POST with json-server? #453

Closed
vsharma2266 opened this Issue Jan 11, 2017 · 11 comments

Comments

Projects
None yet
9 participants
@vsharma2266
Copy link

vsharma2266 commented Jan 11, 2017

Hi,

I am trying to get response using POST. My POST body has some key-value pairs which determine what needs to be responded.
Is it possible to get data back from POST method ?

Thanks

@sanserna

This comment has been minimized.

Copy link

sanserna commented Mar 2, 2017

It would be helpful if they answered this issue... i'am facing the same problem

@typicode

This comment has been minimized.

Copy link
Owner

typicode commented Mar 2, 2017

Hi @vsharma2266 @sanserna,

Out of the box it's not possible, sorry. With REST, making a POST usually mean that you request a change and if you want to query GET is the right verb.

That said, using the project as a module, you can fake it:

// server.js
var jsonServer = require('json-server')
var server = jsonServer.create()
var router = jsonServer.router('db.json')
var middlewares = jsonServer.defaults()

server.use(middlewares)

server.use(jsonServer.bodyParser)
server.use(function (req, res, next) {
  if (req.method === 'POST') {
    // Converts POST to GET and move payload to query params
    // This way it will make JSON Server that it's GET request
    req.method = 'GET'
    req.query = req.body
  }
  // Continue to JSON Server router
  next()
})

// If you need to scope this behaviour to a particular route, use this
server.post('/comments', function (req, res, next) {
  req.method = 'GET'
  req.query = req.body
  next()
})

server.use(router)
server.listen(3000, function () {
  console.log('JSON Server is running')
})

I would suggest checking https://expressjs.com/ docs and https://github.com/typicode/json-server#module

And if you need to customize more, you can also access router's lowdb instance using router.db.

Hope this helps :)

@hopkinson

This comment has been minimized.

Copy link

hopkinson commented Apr 20, 2017

@typicode i tried pasted above code ,but i found that i failed to get data
in routes.json,
'/api/product/stocks_index/list': '/referenceList/:id'
I want '/api/product/stocks_index/list' this api‘s request value is {id:1},and want to turn '/referenceList/:id' into '/referenceList/1' but ,/api/product/stocks_index/list can not change such as/api/product/stocks_index/list?id=1` ..
Or,what can i solve this problem?

@vsharma2266

This comment has been minimized.

Copy link

vsharma2266 commented Aug 14, 2017

Closing as this question is answered.

@appsparkler

This comment has been minimized.

Copy link

appsparkler commented Nov 9, 2017

This is what worked for me:

Instead of writing the server.js file from scratch and executing it; I created a middleware file. The contents of the middleware file are from @typicode's response above:

// middleware-1.js
module.exports = function (req, res, next) {
  if (req.method === 'POST') {
    // Converts POST to GET and move payload to query params
    // This way it will make JSON Server that it's GET request
    req.method = 'GET'
    req.query = req.body
  }
  // Continue to JSON Server router
  next()
}

Next, this is in my json-server.json file:

{
    //...
    "middlewares": ["middleware-1.js"],
    //..
}

The db.json file is as usual with all the data, and finally, executed the code:

json-server db.json

Good Luck.

@mircolac

This comment has been minimized.

Copy link

mircolac commented Dec 1, 2017

@appsparkler thanks a lot for your answer, it helped me fixing a problem in the project i'm working at the moment.

Moreover, while writing the middleware and testing your solution, I discovered a weird behaviour when the query result cointained a field with the same name of a field contained in the POST original body.

I'll explain it better, using an example from the code I wrote

HTTP request

(variable's names are voluntarily changed)

this.http.post<OutputFormat>(EndpointUrl('URL'),
      {
        'foo': foo,
        'bar': bar,
        'baz': 'baz',
        'qux': 'qux'
    })
      .subscribe(
      res => {
        console.log("res is  ",res);
       ...

MIDDLEWARE

module.exports = (req, res, next) => {
...
                req.method ='GET';
                req.query = req.body
                next();
...
}

RESULT:
Everything works fine UNLESS the json at the endpoint contains a field that has the same label of the fields in the req.body ( 'foo', 'bar', 'baz' or 'qux' ).

example:

"endpointYouAskedFor": [
    {
      "foo": {...},
      "someOtherThing": {...}
}

In this case, the result will be an empty res object.
If there was no 'foo' field in the endpoint, everything would have been fine.

I hope this will be useful and spare some hours to someone :)

@appsparkler

This comment has been minimized.

Copy link

appsparkler commented Dec 2, 2017

hi @mircolac

i'm not sure if this would work but another thing that we can include in the middleware is to make the req.body into an empty object before :

// ...
    req.query = req.body;
    delete req.body; //or null (if that works)
// ...

this might avoid the req.body reaching the json-server logic without missing out on the query...

@mircolac

This comment has been minimized.

Copy link

mircolac commented Dec 4, 2017

Hey @appsparkler
That was certainly worth a try, but unfortunately didn't fix the problem!

Thanks anyway :)

@leohxj

This comment has been minimized.

Copy link

leohxj commented Feb 1, 2018

@typicode
I use POST method to make some change, but want to get some response (not the insert resource).

Is there another way which not to make the method to 'get' ?

Thanks.

@leotm

This comment has been minimized.

Copy link

leotm commented Feb 2, 2018

@leohxj Is there an issue with setting your method to get, like so?

server.post('/some/url', (req, res) => {
  req.method = 'GET'
  res.jsonp({ some: "response" })
})

As you can still POST to your server, .then use the response.

@m-e-conroy

This comment has been minimized.

Copy link

m-e-conroy commented Feb 9, 2018

I needed to reroute the URL but resetting req.url wasn't working so I did the following.

const jsonServer = require('json-server');
const server = jsonServer.create();
const router = jsonServer.router('db.json');
const request = require('request');
const middlewares = jsonServer.defaults();

server.use(middlewares);
server.use(jsonServer.bodyParser);

server.post('/login',(req,res,next) => {
  // We don't care if we don't check the password we just want to receive a user back for testing
  let url = 'http://localhost:3000/user?login.username=' + req.body.username;
  request({url: url, json: true},(err, response, body) => {
    res.send(body);
  });
}); // post(/login)

server.use(router);

server.listen(3000, ()=>{
  console.log('http://localhost:3000 Running...');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment