2.0.0
This major release of Surf contains substantial improvements through a variety of changes and additions.
(Note: this is a cumulative list of changes since Surf 1.0.3)
Notable mentions include:
- Uses stable standard library
futures
! - Much more type compatibility with Tide via http-types!
- Re-usable
Client
which is able to make use of connection pooling under the hood. - Reduced generics for
Client
andMiddleware
. - Re-worked
Middleware
to useasync_trait
.
Major Changes
Surf 2 contains some large API changes, as noted here:
http-types
Surf has switched the common backing type interface (surf::http
) from the http (hyperium/http
) crate to http-types, which covers a larger set of HTTP-related functionality than hyperium/http
does, and allows Surf to use the url standard.
This affects any type that came from surf::http
, such as StatusCode
(old|new), and includes some new patterns, such as Body
.
For more information, see this blog post.
Errors
surf::Exception
, which was a plain Box<dyn Error + Send + Sync + 'static>
, is no more.
Surf now exports a structured surf::Error
type, which holds a StatusCode
alongside a dynamic error object.
Just like anyhow
, any error can be cast to this type using the ?
operator.
For more information, see this blog post.
Middleware
New middleware:
use surf::middleware::{Middleware, Next};
use surf::{Client, Request, Response, Result};
#[surf::utils::async_trait]
impl Middleware for Logger {
async fn handle(
&self,
req: Request,
client: Client,
next: Next<'_>,
) -> Result<Response> {
Ok(res)
}
}
RequestBuilder
The top-level convenience request methods, surf::get()
, surf::post()
, etc, now return a RequestBuilder
rather than a Request
directly.
Most RequestBuilder
functions have shorthand names: RequestBuilder::body()
compared to Request::set_body()
.
let res = surf::get("http://example.org") // Now returns a `surf::RequestBuilder`!
.header(a_header, a_value)
.body(a_body)
.await?;
Overall usage was kept the same where possible and reasonable, however now a surf::Client
must be used when using middleware.
let client = surf::client()
.with(some_middleware);
let res = client::post(url)
.header(a_header, a_value)
.body(a_body)
.await?;
Alternately:
let client = surf::client()
.with(some_middleware);
let req = surf::post(url)
.header(a_header, a_value)
.body(a_body);
let res = client.send(req).await?;
Mime
Surf has switched from the mime
crate to surf::http::Mime
from http-types.
For more information, see this blog post.
Additions
- Switched from
hyperium/http
to http-types. surf::Request
added many methods that exist intide::Request
.surf::Response
added many methods that exist intide::Response
.surf::http
, an export ofhttp_types
, similar totide::http
.surf::middleware::Redirect
, a middleware to handle redirect status codes.- All conversions for
Request
andResponse
betweenhttp_types
andsurf
now exist. http_types::{Error, Result}
are re-exported assurf::{Error, Result}
.- A new
h1-client
feature enables the new async-h1 backend. - Transcode responses from non-UTF8 charsets using the on-by-default
encoding
feature.
Removals
- Removed
native-client
feature flag in favor of directcurl-client
default. - Removed
hyper-client
feature flag. (Pending re-addition, see: #234) - Removed
Request::body_string()
,Request::body_json()
, etc.- This functionality is now done via
Body
, orClient::recv_json()
,RequestBuilder::recv_json()
, etc.
- This functionality is now done via
Changes
- Updated to use stable
futures
. wasm-client
feature is no longer automatic and must be set via cargo features.- All client feature flags are now mutually exclusive.
curl-client
is the default. surf::method_name
"one-off" methods now use a shared client internally if the client iscurl-client
. (Default)Client::with_http_client()
is now generic for anyHttpClient
rather than taking anArc<dyn HttpClient>
.- (The http client is still stored internally as a dynamic pointer.)
HttpClient
has been upgraded to 6.0, removingClone
from the built in client backends.surf::Request
changed many methods to be like those intide::Request
.surf::Response
changed many methods to be like those intide::Response
.- Surf now uses
http-types::mime
instead of themime
crate. TryFrom<http_types::Request> for Request
is nowFrom<http_types::Request> for Request
.surf::Client
is no longer generic forC: HttpClient
.- Middleware now receives
surf::Request
and returnsResult<surf::Response, E>
, and no longer requires a generic bound. - Middleware now uses async-trait, which is exported as
surf::utils::async_trait
. - The logger middleware is now exported as
surf::middleware::Logger
. (Note: this middleware is used by default.) surf::{method}()
e.g.surf::get()
now returns asurf::RequestBuilder
rather than asurf::Request
.- Middleware can no longer be set for individual requests.
- Instead, use a
surf::Client
and register middleware viaclient.with(middleware)
. - Then, send the request from that client via
client.send()
e.g.let res = client.send(request).await?;
.
surf::Client
now can set a "base url" for that client viaclient.set_base_url()
.Client
is now built on top ofhttp-client
.surf::url
has been moved tosurf::http::url
, with asurf::Url
shortcut.
Internal
- Reduce copies when parsing URLs.
- Now only depends on
futures_util
rather than all offutures
. wasm-client
now has proper headless browser CI testing.- Use Clippy in CI.
- Set up an MSRV in CI.
- Stop hitting the network when running tests.
Changes since 2.0.0-alpha.7
- Added:
RequestBuilder
now has a.query()
function for setting structured querystrings. - Changed:
Client::send()
andRequestBuilder::send()
are now plain async functions and no longer returnBoxFuture
s. - Changed:
surf::url
has been moved tosurf::http::url
, with asurf::Url
shortcut.