abonander / anterofit Goto Github PK
View Code? Open in Web Editor NEWStrongly typed, asynchronous REST client framework for Rust.
License: Apache License 2.0
Strongly typed, asynchronous REST client framework for Rust.
License: Apache License 2.0
In the readme under "Slower compilation" one of the things you wrote is:
Procedural macros currently have to reparse the token stream instead of reusing compiler datastructures
Is this an actual thing that you have measured? Or is it just a guess?
My experience has always been that macro expansion (including parsing and code generation) is a negligible part of compile time compared to time spent in LLVM.
I am trying to wrap createComment
from the LaunchPad API - search for createComment
on the page as the method has no direct link.
This looks like this in my code:
fn create_comment_by_url(&self, link: &str, subject: &str, content: &str) {
POST("{}", link);
fields! {
"ws.op" => "createComment",
"subject" => subject,
"content" => content
}
}
With link
being a merge_proposal.self_link
.
This does work, however the API states:
On success, the response status will be 201 and the Location header will contain the link to the newly created code_review_comment.
I would like to expose this returned link in my API wrapper, but found no way of extracting a header from the response. Could you give me a hint?
You already have annotations, which is great. Using the annotations you can build OpenAPI description of the API endpoints, which can be used to generate API clients in a number of programming languages.
OpenAPI: https://www.openapis.org
Swagger examples: http://swagger.io
Hi,
I'd like to be able to write something like this:
service! {
pub trait MyService[T] {
// [...]
}
impl for Foo {
// [...]
}
impl[U] for U [where U: AsRef<Foo>] {
// [...]
}
}
I tried to tweak the service!
macro. See little-dude@4fe785a (sorry if I did something horrible here, this is my first time dealing with macros).
I tried it on a simple example (also avalaible on github in case you want to try it):
pub struct Foo<T> {
phantom: PhantomData<T>,
adapter: JsonAdapter,
}
service! {
pub trait MyService[T] {
fn get_next(&self) -> TryWithRaw<Foo<T>> {
GET("")
}
}
impl for Foo<T> {
|this| &this.adapter
}
impl[U] for U [where U: AsRef<Foo<T>>] {
|this| &this.as_ref().adapter
}
}
The generated code look ok, but I'm hitting that error which I'm not sure how to solve:
error[E0277]: the trait bound `anterofit::net::response::TryWithRaw<Foo<T>>: anterofit::net::FromResponse` is not satisfied
--> src/lib.rs:14:1
|
14 | service! {
| ^ the trait `anterofit::net::FromResponse` is not implemented for `anterofit::net::response::TryWithRaw<Foo<T>>`
|
= help: the following implementations were found:
<anterofit::net::response::TryWithRaw<T> as anterofit::net::FromResponse>
= note: this error originates in a macro outside of the current crate
I don't really understand because FromResponse
is implemented for TryWithRaw<T>
, so it should also work for TryWithRaw<Foo<T>>
no?
Allow service methods to view the response and map the value internally.
I think this is as simple as doing hyper = ">=0.9, < 0.11"
for Anterofit and multipart, but it probably needs testing.
I've put a lot of thought into the design of Anterofit, and I've tried to anticipate the most common and the most interesting use-cases, but there's some parts I'm still not quite sure about and I'm interested in feedback.
Should calling service methods immediately submit the request, like Retrofit does, and return Call<...>
?
Should the return type of Request<...>
(or Call<...>
) be explicitly required in service!{}
, instead of being rewritten from the declared return type (assumed to be ()
if not provided)?
Call
/Request
behind a custom user type or impl Future<...>
in order to completely conceal Anterofit as an implementation detail.Should there be request modifiers for mapping the deserialized response to another type, executed on the executor? (This is currently provided as Request::on_complete()
and ::on_result()
, but if the request changed to being immediately submitted then this won't be accessible.)
Allowing user code to run on the executor (via Request::on_complete()
and ::on_result()
) is a potential footgun, in that the user could block the executor (single-threaded by default) with some long-running code and prevent requests from being completed. Is this a significant concern or is a warning in the documentation enough?
Bikeshed: "delegate" vs "wrapper" vs ... ?
There hasn't been much activity lately, dependencies are outdated, all while Rust async ecosystem undergoes rapid evolution.
So, what's the plan?
REST API client frameworks niche is still empty, with just some low-level manual client builders — but nothing like Retrofit (which we are really after).
Hi!
I successfully used anterofit with Hyper 0.9. After upgrading to Hyper 0.10 I get the following error:
96 | adapter = adapter.client(client)
| ^^^^^^ expected struct anterofit::::Client, found struct hyper::Client
|
= note: expected typeanterofit::<unnamed>::Client
= note: found typehyper::Client
The code resulting in the above error tries to set a proxy host and port on the client and then adds it to the adapter's builder:
let client = Client::with_http_proxy(proxy_host, proxy_port); adapter = adapter.client(client)
This fails with the above error since upgrading to Hyper 0.10. It worked fine with Hyper 0.9.
Do you have an idea what's going wrong there?
Keep up the great work!
Cheers!
Amir
Tried setting it up today to interface to an api I use at work, and it does not work. Seems to not know what an https:// URL is...
Do you have any examples that work with https with the latest dependencies?
Thanks!
I started to build a client for the github api: https://github.com/little-dude/ghrs
One thing I could not figure out is how to handle cases where the server returns an error (403
or 404
for example). Ideally, when this happens, I'd like to return an error that contains:
That way the user can take an appropriate action depending on the error.
Currently, I only get a deserialization error, which is not very helpful. Is there a way to do this?
Hi @abonander,
Thanks for the great work on library. Are there any plans to support first stable release of serde?
I’m very new to Rust so maybe I’m misunderstanding something, but I have a feeling the base URL logic isn’t quite right.
My initial understanding was that specifying the base URL would automatically put all of the URLs in the service’s methods under its namespace, e.g. so if the base URL is "/rest/v1"
and the method has GET("/test")
, the resulting URL would be /rest/v1/test
. However, since you use Url::join
for this purpose, the leading slash in the method’s URL acts as an absolute path signifier, resetting the URL to /test
. If I remove this leading slash, it still doesn’t work as expected since the base URL doesn’t have a trailing slash, so Url::join
removes the trailing path component and then appends the other URL, resulting in /rest/test
. While this makes sense for URLs in general, I find this quite confusing in this context and counter-intuitive. My current work-around was to drop the path from the base URL and to add .chain_interceptor(PrependUrl("/rest/v1"))
to the Adapter
builder chain.
Would you consider changing the implementation to avoid this confusing behaviour?
Thanks!
According to Rust release milestone predictions, rustc-serialize is scheduled to be deprecated in next month's beta release of Rust.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.