# 0.16.0

## Features

### Response::Body#to_s does not clear the internal buffer

It's well documented that the response body should be treated as a file, and that calling `.to_s` on a response should be done only once, and the user should not expect the same call to return the same response body again, while suggesting that the first call should be cached in a variable in case it's needed:

```ruby
response = HTTPX.get("https://google.com")
body = response.body.to_s #=> "<html ...."
response.body.to_s #=> ""

# thankfully,it's cached in the body var there.
```

The justification for this behaviour probably had to do with avoiding keeping huge payloads around, but it got a bit lost in git history. It became a feature, not a bug.

However, I got an [issue report](https://gitlab.com/os85/httpx/-/issues/143) that made me change my mind about this behaviour (tl;dr: it broke pattern matching when matching against response bodies more than once).

So now, you can call `.to_s` how many times you want!

```ruby
response = HTTPX.get("https://google.com")
body = response.body.to_s #=> "<html ...."
response.body.to_s #=> "<html ....", still here!
```

Some optimizations were done around how the body is carried forward, and bodies buffered in files will now get properly garbage collected and not leak descriptors behind when users forget to call `.close`.

### grpc plugin improvements

##### build fully-enabled stub from grpc service

The `:grpc` plugin can now build fully-loaded stubs from existing GRPC generic services.

GRPC stubs could be a bit tedious to write when compared to what the `grpc` gem offers, which is, auto-generation from ruby service stubs from protobuf definitions:

```ruby
# service generated from the command:
#
# > grpc_tools_ruby_protoc -I ../../protos --ruby_out=../lib --grpc_out=../lib ../../protos/route_guide.proto
#
require "route_guide_services_pb.rb"

# with httpx, before 0.16
stub = HTTPX.plugin(:grpc).build_stub("localhost:#{server_port}", service: "RouteGuide")
                          .rpc(:GetFeature, Point, Feature)
                          .rpc(:ListFeatures, # ... and so on, all hand stitched

stub.get_feature(# ...

# with httpx 0.16
stub = HTTPX.plugin(:grpc).build_stub("localhost:#{server_port}", service: RouteGuide)
# that's it!
stub.get_feature(# ...
```

#### no google/protobuf direct dependency

`"google/protobuf"` is no longer assumed when using the plugin, i.e. you can use other protobuf serializers, such as https://github.com/ruby-protobuf/protobuf , which supports `jruby` (unlike the former).

### OptionsMethods for plugins

https://gitlab.com/os85/httpx/-/wikis/Custom-Plugins

You can now define an `OptionsMethods` module under your custom plugin to define your own methods. The tl;dr is, that, given the following module below, a new `:bar` option will be available (and the method will be used to set it):

```ruby
module CustomPlugin
  module OptionsMethods
    def option_bar(x) ; x; end
  end
end

HTTPX.plugin(CustomPlugin).with(bar: 2)
```

### cookies plugin: improved jar management

The behaviour of the cookies jar from the `:cookies` plugin was a bit unpredictable in certain conditions, for instance if a "Cookie" header would be passed directly via `.with(headers: {"Cookie" => "a=1"})` and there'd be a value for it already (in same cases, it'd be fully ignored). This would even get worse, if the session had a jar, and a specific set of cookies would be passed to a request(i.e.: `session_with_cookies.get("http://url.get", headers: {"Cookies" => "..."}`).

The behaviour was fixed, and is now specced under https://gitlab.com/os85/httpx/-/blob/master/test/support/requests/plugins/cookies.rb .

## Bugfixes

* Cookies sorting in the `:cookies` plugin jar was fixed for truffleruby;

## Chore

* errors when setting options nnow raise `TypeError` instead of `HTTPX::Error`.
* options are now internally frozen by default, which should protect the internals against accidentally updating them;
* Fixed optimization around options initialization, to prevent needless allocations;