# Introduction to the fauxpas package

#### Scott Chamberlain

#### 2023-05-02

`fauxpas` does http errors!

- HTTP error classes more in line with Ruby/Python/Etc. (psssttt: that is a good thing)
- An error class for each HTTP status in case a user wants to be specific to an HTTP status code, and general purpose handlers for any error
- Work with any of the major R http clients: `crul`, `curl`, `httr` (maybe `RCurl` later)
- Provide flexiblity for what to do on an HTTP error, including custom functions and message templates

There are a lot of functions in this package. Don’t be scared away by that. There are a few major sets of functions that are easy to understand and use:

- There’s a function `http()` that is a general purpose function that handles any HTTP status codes. There’s also a set of functions that follow the pattern `http*()` where `*` is a HTTP status code (e.g. `http201()`). You can use the general purpose function `http()` or the one specific to the status code you are interested in.
- There’s a lower level `R6` class `Error` that is wrapped by `http()` that like `http()` is a general purpose function that handles any HTTP status codes. There’s also a set of `R6` classes that follow the pattern `HTTP*()` where `*` is a HTTP name (e.g. `HTTPGatewayTimeout`). You can use the general purpose class `Error()` or the one specific to the status you are interested in.

`fauxpas` uses httpcode under the hood - which holds all the info about HTTP status codes.

## Install

CRAN version

    install.packages("fauxpas")

Dev version

    # install.packages("remotes")
    remotes::install_github("sckott/fauxpas")

    library("fauxpas")

## Find classes for a HTTP status code

When using `fauxpas` in another package I personally like to use the `HTTP*` classes.

Since these are named with their HTTP reason (e.g. `HTTPGatewayTimeout`), it’s not super straightforward to find them with a status code, which is what one always has as a response from a server. A good way to find these is with a new function `find_error_class()`. Just pass the function a HTTP status code and it will find the matching class.

    (x <- find_error_class(418))
    #> <HTTPTeaPot> object generator
    #>   Inherits from: <Error>
    #>   Public:
    #>     name: HTTPTeaPot
    #>     status_code: 418
    #>     mssg:
    #>     do_verbose: function (response, template = self$message_template_verbose)
    #>     clone: function (deep = FALSE)
    #>   Parent env: <environment: 0x135e88de0>
    #>   Locked objects: TRUE
    #>   Locked class: FALSE
    #>   Portable: TRUE

Which returns the matching error class object, with which you can initialize a new object:

    x$new()
    #> <HTTPTeaPot>
    #>   behavior: stop
    #>   message_template: {{reason}} (HTTP {{status}})
    #>   message_template_verbose: {{reason}} (HTTP {{status}}).\n - {{message}}

If you pass it a status code it doesn’t know about it errors

    find_error_class(999)
    #> Error in find_error_class(999) : no method found for 999

## Use fauxpas with HTTP clients

### crul

    library("crul")
    cli <- HttpClient$new("https://httpbin.org/status/414")
    res <- cli$get()
    http(res)
    #> Error: Request-URI Too Long (HTTP 414).
    http414(res)
    #> Error: Request-URI Too Long (HTTP 414).

    x <- HTTPRequestURITooLong$new()
    x$do_verbose(res)
    #> Error: Request-URI Too Long (HTTP 414).
    #> - The server is refusing to service the request because the Request-URI is
    #>    longer than the server is willing to interpret. This rare condition is only likely
    #>    to occur when a client has improperly converted a POST request to a GET request
    #>    with long query information, when the client has descended into a URI black hole
    #>    of redirection (e.g., a redirected URI prefix that points to a suffix of itself),
    #>    or when the server is under attack by a client attempting to exploit security
    #>    holes present in some servers using fixed-length buffers for reading or
    #>    manipulating the Request-URI.

### curl

    library("curl")
    h <- curl::new_handle()
    curl::handle_setopt(h)
    resp <- curl::curl_fetch_memory("https://httpbin.org/status/404", h)
    http(resp)
    #> Error: Not Found (HTTP 404).
    http404(resp)
    #> Error: Not Found (HTTP 404).

    x <- HTTPNotFound$new()
    x$do_verbose(resp)
    #> Error:  Not Found (HTTP 404).
    #>  - The server has not found anything matching the Request-URI. No indication is
    #> given of whether the condition is temporary or permanent. The 410 (Gone) status
    #> code SHOULD be used if the server knows, through some internally configurable
    #> mechanism, that an old resource is permanently unavailable and has no forwarding
    #> address. #> This status code is commonly used when the server does not wish to
    #> reveal exactly why the request has been refused, or when no other response is
    #> applicable.

### httr

    library("httr")
    res <- GET("https://httpbin.org/status/405")
    http405(res)
    #> Error: Method Not Allowed (HTTP 405).

    x <- HTTPMethodNotAllowed$new()
    x$do_verbose(res)
    #> Error: Method Not Allowed (HTTP 405).
    #>  - The method specified in the Request-Line is not allowed for the resource
    #> identified by the Request-URI. The response MUST include an Allow header
    #> containing a list of valid methods for the requested resource.