liberator/CHANGELOG.md -rw-r--r-- 8.5 KiB
ef0bcd1aRosa Richter Remove FUNDING, use my global .github repo 4 months ago


All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.



  • All exceptions have been renamed to add Exception to their name. This is to adhere to a consistent naming convention that Credo recommends.

#1.4.0 - 2021-03-23


#New Callbacks
  • The handle_error/3 handler has been added. This is a special handler that lets you manipulate the conn after an error is raised, so you can choose your status code and body yourself. (docs) (#33)
  • The maximum_entity_length/1 function. This is used by the valid_entity_length?/1 callback. If the size of the request body is above this size, Liberator will return a status of 413 Request Entity Too Large. (docs)
  • Added the well_formed?/1 function. This function checks the request for general adherence to some form, like if it is valid JSON. It replaces malformed?/1 so that you can return some data after you check for form. (docs)
  • Added the body_exists?/1 function. This is an internal function that, uh, checks to see if the body exists. If it does, it'll grab it, and call valid_entity_length?/1 and the new well_formed?/1 function. So now you can parse the body if it's there, without worrying about conditional logic if it's not there. (docs
#Additions to callbacks
  • You can now return the given conn in decision functions and actions to serve as an affirmative response, as an alternative to returning a plain map, or true. Now you can modify the conn as you see fit.
  • You can now return :ok or :error tuples from decisions, actions, and handlers. Returning {:error, term} will invoke the new handle_error/3 function.

Docs for callbacks

#Added internationalization
  • Internationalization is now supported via Gettext! Liberator already finds the best language for each request, now it also sets the locale using Gettext.put_locale/1. Just call gettext directly in your Resources. (docs) (#8, #10)
#Debugging and tracing upgrades
  • Tracing individual step duration is now available. Access the :duration key for each decision in the tracing list to get that decision's duration, in native time units.
  • You can now generate a Graphviz file for either the default decision tree or your own resource's decision tree using the mix liberator.chart mix task.
  • Telemetry is now sent upon each request. Three events [:liberator, :request, :start], [:liberator, :request, :stop], and [:liberator, :request, :exception] are sent. See the docs for Liberator.Resource for more information.

Docs for debugging and tracing


  • The Vary header is now served by default, with a value of Accept-Encoding and Accept-Language.
  • Now serves the location header if you've returned a map with the :location key, or assigned it on the conn.
  • Some decision functions were rearranged.
  • Raised errors are now wrapped in custom exceptions. They're the same errors with the same messages, just with different wrapper types.
  • Entries in the trace list have changed from tuples to maps in order to support more tracing information. The step is now a map member named :step, and the value is :value


  • The malformed?/1 is now deprecated, use well_formed?/1 instead. This lets that decision function return data, and it's the ideal place for parsing the body. (#15)


  • The etag header is now included in the response, if you have overridden it. (#17)
  • Now serves the last-modified header based on the return value from the last_modified/1 callback. (#18)
  • Non-printable-String return values from handlers will now be passed through inspect/1 when the content type is text/plain. Printable strings will be passed through without hassle. (#7)
  • All responses now include an allow header, fixing the cases where one was required but not provided, like in an OPTIONS request, and when returning a 405 Method Not Allowed. (#9, #12)

#1.3.0 - 2020-10-13


  • The :log argument to the :trace option. Add a trace: :log option to your module's use statement, and every request will be logged with a trace. The log message even includes a request ID from Plug.RequestId, if you have one. (#4)
  • The :decision_tree_overrides argument to Liberator.Resource. This is an advanced feature that lets users override parts of the decision tree that Liberator evaluates. Want to change the ordering of some decisions, or add new ones? This is the way! (#5)
  • The :handler_status_overrides argument to Liberator.Resource. This is an advanced feature that lets users override status codes associated with handlers. It's mostly useful for those wanting to implement their own new statuses that Liberator doesn't support.
  • The :action_followup_overrides argument to Liberator.Resource. This is an advanced feature that lets users override the functions called immediately after actions. It's mostly useful for those wanting to implement their own new actions that Liberator doesn't support.

#1.2.0 - 2020-10-12


  • The 402 Payment Required status, along with related callbacks payment_required? and handle_payment_required/1.
  • The 451 Unavailable for Legal Reasons status, along with related callbacks unavailable_for_legal_reasons?/1 and handle_unavailable_for_legal_reasons/1.
  • The 429 Too Many Requests status, along with related callbacks too_many_requests?/1 and handle_too_many_requests/1. If you return a map containing a :retry_after value, Liberator will use that to set a retry-after header.
  • You can also return a :retry_after value from any other decision function, like service_available?/1, or moved_permanently?/1, for the same effect. See MDN's docs on the retry-after header for more information on why you'd want to do this.


  • Dates in headers are now parsed properly. (#1)

#1.1.0 - 2020-10-04


  • This changelog!
  • The :trace option: Add trace: :headers to your use Liberator.Resource statement to get an x-liberator-trace header added to responses, and see the result of all decisions.
  • Compression options: deflate, gzip, and identity.


  • Codecs are now configurable. Set the :media_types and :encodings map in Liberator's config to add your own codecs.


  • Liberator.Resource no longer calls use Timex, so your context is less polluted.


  • Better wildcard handling during content negotiation
  • Content negotiation actually obeys q-values for priority

#1.0.0 - 2020-10-02


  • Basic decision tree navigation