UNPKG

@rails/request.js

Version:

A tiny Fetch API wrapper that allows you to make http requests without need to handle to send the CSRF Token on every request

230 lines (148 loc) 6.21 kB
# Rails Request.JS Rails Request.JS encapsulates the logic to send by default some headers that are required by rails applications like the `X-CSRF-Token`. # Install ## Asset Pipeline Install the [requestjs-rails](https://github.com/rails/requestjs-rails) gem and follow the step described there. ## Webpacker/Esbuild ### npm ``` npm i @rails/request.js ``` ### yarn ```shell yarn add @rails/request.js ``` # How to use Just import the `FetchRequest` class from the package and instantiate it passing the request `method`, `url`, `options`, then call `await request.perform()` and do what you need with the response. Example: ```js import { FetchRequest } from '@rails/request.js' .... async myMethod () { const request = new FetchRequest('post', 'localhost:3000/my_endpoint', { body: JSON.stringify({ name: 'Request.JS' }) }) const response = await request.perform() if (response.ok) { const body = await response.text // Do whatever do you want with the response body // You also are able to call `response.html` or `response.json`, be aware that if you call `response.json` and the response contentType isn't `application/json` there will be raised an error. } } ``` #### Shorthand methods Alternatively, you can use a shorthand version for the main HTTP verbs, `get`, `post`, `put`, `patch` or `destroy`. Example: ```js import { get, post, put, patch, destroy } from '@rails/request.js' ... async myMethod () { const response = await post('localhost:3000/my_endpoint', { body: JSON.stringify({ name: 'Request.JS' }) }) if (response.ok) { const body = await response.json ... } } ``` #### Request Options You can pass options to a request as the last argument. For example: ```javascript post("/my_endpoint", { body: {}, contentType: "application/json", headers: {}, query: {}, responseKind: "html" }) ``` ##### body This is the `body` for POST requests. You can pass in a Javascript object, FormData, Files, strings, etc. Request.js will automatically JSON stringify the `body` if the content type is `application/json`. ##### contentType When provided this value will be sent in the `Content-Type` header. When not provided Request.JS will send nothing when the `body` of the request is `null` or an instance of `FormData`, when the `body` is an instance of a `File` then the type of the file will be sent and `application/json` will be sent if none of the prior conditions matches. ##### headers Adds additional headers to the request. `X-CSRF-Token` and `Content-Type` are automatically included. ##### credentials Specifies the `credentials` option. Default is `same-origin`. ##### query Appends query parameters to the URL. Query params in the URL are preserved and merged with the query options. Accepts `Object`, `FormData` or `URLSearchParams`. ##### responseKind Specifies which response format will be accepted. Default is `html`. Options are `html`, `turbo-stream`, `json`, and `script`. ##### keepalive Specifies the `keepalive` option. Default is `false`. #### Turbo Streams Request.JS will automatically process Turbo Stream responses. Ensure that your Javascript sets the `window.Turbo` global variable: ```javascript import { Turbo } from "@hotwired/turbo-rails" window.Turbo = Turbo ``` Since [v7.0.0-beta.6](https://github.com/hotwired/turbo/releases/tag/v7.0.0-beta.6) Turbo sets `window.Turbo` automatically. Request.JS will also use Turbo's `fetch` to include the `X-Turbo-Request-ID` header in the request (see [#73](https://github.com/rails/request.js/issues/73)). #### Script Responses Request.JS will automatically activate script tags in the response (see [#48](https://github.com/rails/request.js/issues/48)). #### Request Interceptor To authenticate fetch requests (eg. with Bearer token) you can use request interceptor. It allows pausing request invocation for fetching token and then adding it to headers: ```javascript import { RequestInterceptor } from '@rails/request.js' // ... // Set interceptor RequestInterceptor.register(async (request) => { const token = await getSessionToken(window.app) request.addHeader('Authorization', `Bearer ${token}`) }) // Reset interceptor RequestInterceptor.reset() ``` #### Before and after hooks Wrap the request `Promise` with your own code. Just pure and simple JavaScript like this: ```javascript import { FetchRequest } from "@rails/request.js" import { navigator } from "@hotwired/turbo" function showProgressBar() { navigator.delegate.adapter.progressBar.setValue(0) navigator.delegate.adapter.progressBar.show() } function hideProgressBar() { navigator.delegate.adapter.progressBar.setValue(1) navigator.delegate.adapter.progressBar.hide() } export function withProgress(request) { showProgressBar() return request.then((response) => { hideProgressBar() return response }) } export function get(url, options) { const request = new FetchRequest("get", url, options) return withProgress(request.perform()) } ``` ## Response ### statusCode Returns the response status. ### ok Returns true if the response was successful. ### unauthenticated Returns true if the response has a `401` status code. ### authenticationURL Returns the value contained in the `WWW-Authenticate` header. ### contentType Returns the response content-type. ### html Returns the html body, if the content type of the response isn't `html` then will be returned a rejected promise. ### json Returns the json body, if the content type of the response isn't `json` then will be returned a rejected promise. ### headers Returns the response headers. # Known Issues `FetchRequest` sets a `"X-Requested-With": "XmlHttpRequest"` header. If you have not upgraded to Turbo and still use `Turbolinks` in your Gemfile, this means you will not be able to check if the request was redirected. ```js const request = new FetchRequest('post', 'localhost:3000/my_endpoint', { body: JSON.stringify({ name: 'Request.JS' }) }) const response = await request.perform() response.redirected // => will always be false. ``` # License Rails Request.JS is released under the [MIT License](LICENSE). © 37signals, LLC.