Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to use dynamic paths? #906

Open
hansmbakker opened this issue Apr 17, 2020 · 11 comments
Open

Is it possible to use dynamic paths? #906

hansmbakker opened this issue Apr 17, 2020 · 11 comments
Labels

Comments

@hansmbakker
Copy link
Contributor

hansmbakker commented Apr 17, 2020

I am writing a rest client for Azure Durable Functions.

They work with an HTTP endpoint that starts a long-running task, and it immediately returns a JSON response with "follow-up urls".

Example (urls will have dynamic details at runtime):

{
    "id": "abc123",
    "purgeHistoryDeleteUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX",
    "sendEventPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123/raiseEvent/{eventName}?code=XXX",
    "statusQueryGetUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123?code=XXX",
    "terminatePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123/terminate?reason={text}&code=XXX"
}

Now I want to create a rest client for at least the Status Query endpoint and the Terminate endpoint. These endpoints have dynamic urls / querystring parameters.

If I try to supply them like so:

[Get("{statusQueryUri}")]
        Task<StatusQueryResponse<SomeResponse>> QueryStatus(string statusQueryUrl);

and I use Uri.PathAndQuery to supply the relative path + querystring, then I get a runtime error when calling RestService.For<IFunctionApi>("...").

Refit complains that {statusQueryUri} is not of the form of /foo/bar/baz.

How can I dynamically supply the relative part of the url + querystring while still getting the benefits of refit (adding headers, defining methods and return types via an interface)?

Update
@Paul-N created #1368 which is basically the same ask (possibility of supporting dynamic URLs within Refit's request/response handling and code generation).

His suggested approach ([Url] attribute following Retrofit's example) looks good to me and he made an implementation for it.

@jeroenkoknl
Copy link

jeroenkoknl commented Jul 6, 2020

I would like to request this feature as well. Some APIs have URLs in the response that can be called for subsequent requests. For example:

Request:

GET http://foo/bar/

Response:

{
   "next": "/bar/?from=10",
   "results":  [ { }, { } ]
}

In this example the client can get the next results by requesting the URL returned in the next property.

To support this scenario, I suggest to introduce a Url attribute, similar to what is done in Retrofit:

[Get]
Task<Result> Get([Url] string url)

@Arshia001
Copy link

Need this as well.

@amrit-hop
Copy link

this would be helpful for us too.

@GalaxiaGuy
Copy link

GalaxiaGuy commented Apr 20, 2021

I have a proof of concept for an implementation of this here:

https://github.com/GalaxiaGuy/refit/pull/1/files

Should the parameter for the path on GetAttribute, PostAttribute etc. be made optional? Or maybe a well defined constant should be used? Either way more validation around using illogical combinations should exist.

GitHub
Dynamic URL proof of concept for #906 .

@AmiTimA
Copy link

AmiTimA commented Aug 21, 2021

All was well till long running API endpoints appeared, which is returning another URL to check status after some time. Need this feature.

@uuggene
Copy link

uuggene commented Jan 20, 2023

Need this also.
Scenario:
I need to make a post request to callback url, which can be any url (any host, any path, any query string).

@mdschweda
Copy link

mdschweda commented May 4, 2023

Need this for endpoints with catch-all route templates, e.g.

class DocumentsController : Controller {

    [HttpGet("{**path}")]
    public Task<IActionResult> Download(string path) {
        // ...
    }

}

And then define the API just like so:

interface IDocumentsApi {

    [Get("/documents/{**path}")]
    Task<IApiResponse> Download(string path);

    // or

    [Get("/documents/{path}")]
    Task<IApiResponse> Download([PathUriFormat(UriFormat.Unescaped)] string path);

}

@xrootpi
Copy link

xrootpi commented Jul 8, 2023

@mdschweda it actually works with the following

 [Get("/{**path}")]
    [QueryUriFormat(UriFormat.Unescaped)]
    Task<object> GetNext(string path);
    

You will only have to ensure first '/' is not part of the path for example with following data

{
"next": "/bar/?from=10",
}

    var next = "/bar/?from=10";
    var pathQ = next .Remove(0,1); // This is a work around for bug
    var x = await myApi.GetNext(pathQ);

@mdschweda
Copy link

@mdschweda it actually works with the following

 [Get("/{**path}")]
    [QueryUriFormat(UriFormat.Unescaped)]
    Task<object> GetNext(string path);
    

You will only have to ensure first '/' is not part of the path for example with following data

{ "next": "/bar/?from=10", }

    var next = "/bar/?from=10";
    var pathQ = next .Remove(0,1); // This is a work around for bug
    var x = await myApi.GetNext(pathQ);

Thanks

@onionhammer
Copy link

This would be very useful.

@hansmbakker
Copy link
Contributor Author

@Paul-N created #1368 which is basically the same ask (possibility of supporting dynamic URLs within Refit's request/response handling and code generation).

His suggested approach ([Url] attribute following Retrofit's example) looks good to me and he made an implementation for it.

@ChrisPulman I think one of these issues can be marked duplicate - what do you suggest? And regarding implementation, is this something you could help moving forward?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests