Grails REST API config

  • access control allow origin
  • hidden OPTIONS method for non-https
  • url mappings and naming convensions

Access control allow origin

Filter: enable Angular dev on a different port

if (Environment.developmentMode) {
  header("Access-Control-Allow-Origin", "http://localhost:4200")
  header("Access-Control-Allow-Credentials", "true")
  header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS, PATCH")
  header("Access-Control-Max-Age", "86400")

  response.addHeader("Access-Control-Allow-Headers", "Authorization, Accept, Content-Type")

  // In dev, always allow preflight OPTIONS cross origin request
  if (ControllerPermission.isOptionMethodInDev(Environment.developmentMode, request.method)) {
    render status: 200
    return false // skip other filters (no more security check)
  }
  else {
    return true // continue to run other filters
  }
}

Each controller: have to provide an options action, so that Grails can make the browser happy

def options() {
  render status: 200 // action to allow dev cross origin preflight OPTIONS request
}

Automatic OPTIONS method on the request

Cross domain non-https API requests would send an OPTIONS preflight request without Authorization header.
It returns 302 status and causes the subsequent e.g. GET request to be redirected.

To avoid this problem, we can:

For more information, refer to:

Url mappings and naming convensions

REST web service endpoints should have plural nouns as their names. The below specifies the convensions for the action names matching related http methods.

  • endpoint without id + GET
  • endpoint with id + method
  • specific endpoint
"/api/$controller" {
  action = [
      GET    : "index", // the index action, which is optional in Grails, returns all the items
      OPTIONS: "options" // allow options for preflight request in dev
  ]
}

/*
* Rest web services - for all the controllers in the api package ending with a plural word
* */
"/api/$controller/$id" {
  action = [
      GET    : "get", // show - get one item by id
      PUT    : "put",  // update - by submitting full content
      DELETE : "delete", // delete - delete one item by id
      POST   : "post", // create - by submitting full content
      PATCH  : "patch", // update - by submitting partial content - preferred not to use this for code simplicity
      OPTIONS: "options" // allow options for preflight request in dev, bypassed by AngularDevFilters
  ]
}

/*
* Specific REST requests
* */
"/api/$controller/$action" {
  constraints {}
}

Note:

  • Most of the time, listing all the items require supplying a foreign key id (e.g. get all the charts for category 32)

results matching ""

    No results matching ""