github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/docs_src/src/guide/basics/responses.md (about)

     1  ---
     2  meta:
     3    - name: "og:title"
     4      content: "Responses - Goyave"
     5    - name: "twitter:title"
     6      content: "Responses - Goyave"
     7    - name: "title"
     8      content: "Responses - Goyave"
     9  ---
    10  
    11  # Responses
    12  
    13  [[toc]]
    14  
    15  ## Introduction
    16  
    17  Handlers receive a `goyave.Response` and a `goyave.Request` as parameters.
    18  
    19  `goyave.Response` implements `http.ResponseWriter`. This object brings a number of convenient methods to write HTTP responses.
    20  
    21  If you didn't write anything before the request lifecycle ends, `204 No Content` is automatically written.
    22  
    23  ## Reference
    24  
    25  All functions below require the `goyave` package to be imported.
    26  
    27  ``` go
    28  import "github.com/System-Glitch/goyave/v2"
    29  ```
    30  
    31  **List of response methods**:
    32  ::: table
    33  [GetStatus](#response-getstatus)
    34  [GetError](#response-geterror)
    35  [Header](#response-header)
    36  [Status](#response-status)
    37  [JSON](#response-json)
    38  [String](#response-string)
    39  [Write](#response-write)
    40  [File](#response-file)
    41  [Download](#response-download)
    42  [Error](#response-error)
    43  [Cookie](#response-cookie)
    44  [Redirect](#response-redirect)
    45  [TemporaryRedirect](#response-temporaryredirect)
    46  [Render](#response-render)
    47  [RenderHTML](#response-renderhtml)
    48  [HandleDatabaseError](#response-handledatabaseerror)
    49  :::
    50  
    51  #### Response.GetStatus
    52  
    53  Returns the response code for this request or `0` if not yet set.
    54  
    55  | Parameters | Return |
    56  |------------|--------|
    57  |            | `int`  |
    58  
    59  **Example:**
    60  ``` go
    61  fmt.Println(response.GetStatus()) // 200
    62  ```
    63  
    64  #### Response.GetError
    65  
    66  Returns the value which caused a panic in the request's handling, or `nil`. The response error is also set when [`Error()`](#response-error) is called.
    67  
    68  This method is mainly used in [status handlers](../advanced/status-handlers.html).
    69  
    70  | Parameters | Return        |
    71  |------------|---------------|
    72  |            | `interface{}` |
    73  
    74  **Example:**
    75  ``` go
    76  fmt.Println(response.GetError()) // "panic: something wrong happened"
    77  ```
    78  
    79  #### Response.Header
    80  
    81  Returns the Header map that will be sent.
    82  
    83  | Parameters | Return        |
    84  |------------|---------------|
    85  |            | `http.Header` |
    86  
    87  **Example:**
    88  ``` go
    89  header := response.Header()
    90  header.Set("Content-Type", "application/json")
    91  ```
    92  
    93  #### Response.Status
    94  
    95  Write the given status code. Calling this method a second time will have no effect.
    96  
    97  | Parameters   | Return |
    98  |--------------|--------|
    99  | `status int` | `void` |
   100  
   101  **Example:**
   102  ``` go
   103  response.Status(http.StatusOK)
   104  ```
   105  
   106  #### Response.JSON
   107  
   108  Write JSON data as a response. This method automatically sets the `Content-Type` header.
   109  
   110  | Parameters         | Return  |
   111  |--------------------|---------|
   112  | `responseCode int` | `error` |
   113  | `data interface{}` |         |
   114  
   115  **Example:**
   116  ``` go
   117  response.JSON(http.StatusOK, map[string]interface{}{
   118      "name": "John Doe",
   119      "tags": []string{"tag1", "tag2"},
   120  })
   121  ```
   122  
   123  #### Response.String
   124  
   125  Write a string as a response.
   126  
   127  | Parameters         | Return  |
   128  |--------------------|---------|
   129  | `responseCode int` | `error` |
   130  | `message string`   |         |
   131  
   132  **Example:**
   133  ``` go
   134  response.String(http.StatusOK, "Hello there!")
   135  ```
   136  
   137  #### Response.Write
   138  
   139  Write the data as a response. Can be used to write in-memory files. This method can be called successively.
   140  
   141  Returns the number of bytes written.
   142  
   143  | Parameters    | Return  |
   144  |---------------|---------|
   145  | `data []byte` | `int`   |
   146  |               | `error` |
   147  
   148  **Example:**
   149  ``` go
   150  response.Write([]byte("Hello there!"))
   151  ```
   152  
   153  #### Response.File
   154  
   155  Write a file as an inline element.
   156  
   157  Automatically detects the file MIME type and sets the "Content-Type" header accordingly. If the file doesn't exist, respond with status `404 Not Found`. The given path can be relative or absolute.
   158  
   159  If you want the file to be sent as a download ("Content-Disposition: attachment"), use the `Download` function instead.
   160  
   161  | Parameters    | Return  |
   162  |---------------|---------|
   163  | `file string` | `error` |
   164  
   165  **Example:**
   166  ``` go
   167  response.File("/path/to/file")
   168  ```
   169  
   170  #### Response.Download
   171  
   172  Write a file as an attachment element.
   173  
   174  Automatically detects the file MIME type and sets the "Content-Type" header accordingly. If the file doesn't exist, respond with status `404 Not Found`. The given path can be relative or absolute.
   175  
   176  The `fileName` parameter defines the name the client will see. In other words, it sets the header "Content-Disposition" to "attachment; filename="${fileName}""
   177  
   178  If you want the file to be sent as an inline element ("Content-Disposition: inline"), use the `File` function instead.
   179  
   180  | Parameters        | Return  |
   181  |-------------------|---------|
   182  | `file string`     | `error` |
   183  | `fileName string` |         |
   184  
   185  **Example:**
   186  ``` go
   187  response.Download("/path/to/file", "awesome.txt")
   188  ```
   189  
   190  #### Response.Error
   191  
   192  Print the error in the console and return it with an error code `500`.
   193  
   194  If debugging is enabled in the config, the error is also written in the response using the JSON format, and the stacktrace is printed in the console. If debugging is not enabled, only the stauts code is set, which means you can still write to the response, or use your error [status handler](../advanced/status-handlers.html).
   195  
   196  | Parameters        | Return  |
   197  |-------------------|---------|
   198  | `err interface{}` | `error` |
   199  
   200  **Example:**
   201  ``` go
   202  v, err := strconv.Atoi("-42")
   203  response.Error(err)
   204  ```
   205  
   206  #### Response.Cookie
   207  
   208  Add a Set-Cookie header to the response. The provided cookie must have a valid Name. Invalid cookies may be silently dropped.
   209  
   210  | Parameters             | Return |
   211  |------------------------|--------|
   212  | `cookie *http.Cookie*` | `void` |
   213  
   214  **Example:**
   215  ``` go
   216  cookie := &http.Cookie{
   217      Name:  "cookie-name",
   218      Value: "value",
   219  }
   220  response.Cookie(cookie)
   221  ```
   222  
   223  ::: warning
   224  Protect yourself from [CSRF attacks](https://en.wikipedia.org/wiki/Cross-site_request_forgery) when using cookies!
   225  :::
   226  
   227  #### Response.Redirect
   228  
   229  Send a permanent redirect response. (HTTP 308)
   230  
   231  | Parameters   | Return |
   232  |--------------|--------|
   233  | `url string` | `void` |
   234  
   235  **Example:**
   236  ``` go
   237  response.Redirect("/login")
   238  ```
   239  
   240  #### Response.TemporaryRedirect
   241  
   242  Send a temporary redirect response. (HTTP 307)
   243  
   244  | Parameters   | Return |
   245  |--------------|--------|
   246  | `url string` | `void` |
   247  
   248  **Example:**
   249  ``` go
   250  response.TemporaryRedirect("/maintenance")
   251  ```
   252  
   253  #### Response.Render
   254  
   255  Render a text template with the given data. This method uses the [Go's template API](https://golang.org/pkg/text/template/).
   256  
   257  The template path is relative to the `resources/template` directory.
   258  
   259  | Parameters            | Return  |
   260  |-----------------------|---------|
   261  | `responseCode int`    | `error` |
   262  | `templatePath string` |         |
   263  | `data interface{}`    |         |
   264  
   265  **Example:**
   266  ``` go
   267  type Inventory struct {
   268  	Material string
   269  	Count    uint
   270  }
   271  
   272  sweaters := Inventory{"wool", 17}
   273  
   274  // data can also be a map[string]interface{}
   275  // Here, "resources/template/template.txt" will be used.
   276  if err := response.Render(http.StatusOK, "template.txt", sweaters); err != nil {
   277  	response.Error(err)
   278  }
   279  ```
   280  
   281  #### Response.RenderHTML
   282  
   283  Render an HTML template with the given data. This method uses the [Go's template API](https://golang.org/pkg/html/template/).
   284  
   285  The template path is relative to the `resources/template` directory.
   286  
   287  | Parameters            | Return  |
   288  |-----------------------|---------|
   289  | `responseCode int`    | `error` |
   290  | `templatePath string` |         |
   291  | `data interface{}`    |         |
   292  
   293  **Example:**
   294  ``` go
   295  type Inventory struct {
   296  	Material string
   297  	Count    uint
   298  }
   299  
   300  sweaters := Inventory{"wool", 17}
   301  
   302  // data can also be a map[string]interface{}
   303  // Here, "resources/template/inventory.html" will be used.
   304  if err := response.RenderHTML(http.StatusOK, "inventory.html", sweaters); err != nil {
   305  	response.Error(err)
   306  }
   307  ```
   308  
   309  #### Response.HandleDatabaseError
   310  
   311  Takes a database query result and checks if any error has occurred.
   312  
   313  Automatically writes HTTP status code 404 Not Found if the error is a "Not found" error. Calls `Response.Error()` if there is another type of error.
   314  
   315  Returns `true` if there is no error.
   316  
   317  | Parameters    | Return |
   318  |---------------|--------|
   319  | `db *gorm.DB` | `bool` |
   320  
   321  **Example:**
   322  ``` go
   323  product := model.Product{}
   324  result := database.GetConnection().First(&product, id)
   325  if response.HandleDatabaseError(result) {
   326      response.JSON(http.StatusOK, product)
   327  }
   328  ```
   329  
   330  ## Chained writers
   331  
   332  <p><Badge text="Since v2.7.0"/></p>
   333  
   334  It is possible to replace the `io.Writer` used by the `Response` object. This allows for more flexibility when manipulating the data you send to the client. It makes it easier to compress your response, write it to logs, etc. You can chain as many writers as you want. The writer replacement is most often done in a middleware. If your writer implements `io.Closer`, it will be automatically closed at the end of the request's lifecycle.
   335  
   336  The following example is a simple implementation of a middleware logging everything sent by the server to the client.
   337  ``` go
   338  import (
   339  	"io"
   340  	"log"
   341  
   342  	"github.com/System-Glitch/goyave/v2"
   343  )
   344  
   345  type LogWriter struct {
   346  	writer   io.Writer
   347  	response *goyave.Response
   348  	body     []byte
   349  }
   350  
   351  func (w *LogWriter) Write(b []byte) (int, error) {
   352  	w.body = append(w.body, b...)
   353  	return w.writer.Write(b)
   354  }
   355  
   356  func (w *LogWriter) Close() error {
   357      // The chained writer MUST be closed if it's closeable.
   358  	// Therefore, all chained writers should implement io.Closer.
   359  
   360  	goyave.Logger.Println("RESPONSE", w.response.GetStatus(), string(w.body))
   361  
   362  	if wr, ok := w.writer.(io.Closer); ok {
   363  		return wr.Close()
   364  	}
   365  	return nil
   366  }
   367  
   368  func LogMiddleware(next goyave.Handler) goyave.Handler {
   369  	return func(response *goyave.Response, request *goyave.Request) {
   370  		logWriter := &LogWriter{
   371  			writer:   response.Writer(),
   372  			response: response,
   373  		}
   374  		response.SetWriter(logWriter)
   375  
   376  		next(response, request)
   377  	}
   378  }
   379  ```
   380  
   381  #### Response.Writer
   382  
   383  Return the current writer used to write the response.
   384  
   385  Note that the returned writer is not necessarily a `http.ResponseWriter`, as it can be replaced using `SetWriter`.
   386  
   387  | Parameters | Return      |
   388  |------------|-------------|
   389  |            | `io.Writer` |
   390  
   391  #### Response.SetWriter
   392  
   393  Set the writer used to write the response.
   394  
   395  This can be used to chain writers, for example to enable gzip compression, or for logging. The original `http.ResponseWriter` is always kept.
   396  
   397  | Parameters         | Return |
   398  |--------------------|--------|
   399  | `writer io.Writer` |        |