2

Using angular v1.3.1 i got a singular the following problem trying to implement a facade for making http request to a REST + JSON interface in the backend of the web app.

I got something like this in the code:

findSomething(value: number): ng.IPromise<api.DrugIndication[]> {
  const getParams = { 'param' : 'value' };
  const config:ng.IRequestShortcutConfig = {
    headers: {
      "Content-Type" : "application/json"
    },
    data: getParams
  }
  return this.$http.get(url,config);
}

And when the times comes to invoke it, i got an 400 Bad Request (btw: Great name for a band!) because the backend (made with Play for Scala) rejects the request inmediately. So making an inspection in the request i see that no data is being send in the body of the request/message.

So how i can send some data in the body of and HTTP Get request using angular "$http.get"?

Additional info: This doesn't happen if i the make request using the curl command from an ubuntu shell. So probably is an problem between Chrome and angular.js

Victor
  • 3,348
  • 2
  • 29
  • 55
  • sounds like a CORS issue, most likely – Claies Mar 29 '17 at 20:23
  • why don't you use POST? – Pankaj Parkar Mar 29 '17 at 20:25
  • @PankajParkar because usually a find request typically is performed with GET method.. but i could change for a POST, and that would work. Even so, i would like to know is someone knows a workaround for this that doesn't involve changing the URL request method. – Victor Mar 29 '17 at 20:35
  • A GET request cannot have a body in HTTP. This is not specific to Chrome or Angular, it's by definition in the HTTP specifications. If you want to send a body in your request, it needs to be a POST, PUT or PATCH. Curl will automatically switch to POST as soon as you specify any data to send, as can be seen if you add -v in your invocation. – jcaron Mar 29 '17 at 21:37
  • 1
    Why on Earth, would you need a body for a GET request..? – n00dl3 Mar 29 '17 at 22:34
  • 1
    lads, as far I know there is no rule that explicitly forbids to send a body in a GET request, in a matter of fact I made it via curl. – Victor Mar 30 '17 at 14:31
  • 1
    probably related: http://stackoverflow.com/a/983458/2495283 – Claies Mar 30 '17 at 19:13

2 Answers2

1

If you inspect the network tab in chrome development tools you will see that this is a pre-flight OPTIONS request (Cross-Origin Resource Sharing (CORS)).

You have two ways to solve this.

  1. Client side (this requires that your server does not require the application/json value)

    • GET, POST, HEAD methods only
    • Only browser set headers plus these
    • Content-Type only with:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain
  2. Server side

    • Set something like this as a middleware on your server framework:

      if r.Method == "OPTIONS" {
          w.Header().Set("Access-Control-Allow-Origin", "*")
          w.Header().Set("Access-Control-Allow-Methods", "GET")
          w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
          w.Header().Set("Access-Control-Max-Age", "86400") // firefox: max 24h, chrome 10min
          return
      }
      

For your specific framework this should work

petul
  • 943
  • 9
  • 16
  • Thanks for the info, could be useful, but the problem isn't CORS. I suspect that angular js or Chrome are enforcing the fact stated at the "The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI." (extracted from https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html). I guess, there is no point in trying to force my "naive" approach.. i will use get with URL params. – Victor Mar 30 '17 at 15:18
1

Using config.data will send the data in the request body, use

config.params = getParams 

This is from the documentation :

params – {Object.} – Map of strings or objects which will be serialized with the paramSerializer and appended as GET parameters