retrofit icon indicating copy to clipboard operation
retrofit copied to clipboard

POST to a dynamic absolute URL does not work (but works with Apache HttpClient)

Open mzattera opened this issue 2 years ago • 4 comments

I need to POST to an URL like https://xxxx.eu-west-1.aws.endpoints.huggingface.cloud (Hugging Face Inference Endpoint), however if I use the below API definition:

	@POST
	Single<String> myMethod(@Url @NonNull String url, @Body MyRequest req);

and I call

       String resp = myMethod("https://xxxx.eu-west-1.aws.endpoints.huggingface.cloud", req);

Retrofit POSTs to https://xxxx.eu-west-1.aws.endpoints.huggingface.cloud/ which does not work (notice the trailing /).

mzattera avatar Jun 03 '23 16:06 mzattera

Those URLs are equivalent. Both will result in an HTTP request which looks like

POST / HTTP/1.1
Host: xxxx.eu-west-1.aws.endpoints.huggingface.cloud

Being sent to the IP that host resolves to.

JakeWharton avatar Jun 03 '23 17:06 JakeWharton

Thanks Jake, this is what I think too however, there is something weird happening when I pass a full URL.

In the attached example, I call the same API using Apache HttpClient and Retrofit (I think I am creating the very same request). The former works well but Retrofit doesn't . However, the same Retrofit call works with a relative URL (model name), so it seems there is nothing wrong in the request, in terms of parameters and headers.

Test.zip (the endpoint in the code is public and active, so you should be able to test this yourself)

The program will produce below output:

---[Apache HtttpClient with URL: https://by62y2zqbeqalfay.eu-west-1.aws.endpoints.huggingface.cloud]------------
HTTP/1.1 200 OK
---------------
[ [ {
  "generated_text" : "Alan Turing was able to perform a \"massive computer simulation\" — which involved several \"trivial\" computer simulations of real-world situations — where the algorithm was based on Turing's mathematical formulation of the Turing machine, and which was performed through an"
} ] ]
---------------
---[Retrofit 2 with URL: https://by62y2zqbeqalfay.eu-west-1.aws.endpoints.huggingface.cloud]------------
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by retrofit2.Platform (file:/D:/.m2/repository/com/squareup/retrofit2/retrofit/2.9.0/retrofit-2.9.0.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of retrofit2.Platform
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
retrofit2.adapter.rxjava2.HttpException: HTTP 400 Bad Request
	at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:57)
	at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:38)
	at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:48)
	at io.reactivex.Observable.subscribe(Observable.java:10151)
	at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:35)
	at io.reactivex.Observable.subscribe(Observable.java:10151)
	at io.reactivex.internal.operators.observable.ObservableSingleSingle.subscribeActual(ObservableSingleSingle.java:35)
	at io.reactivex.Single.subscribe(Single.java:2517)
	at io.reactivex.Single.blockingGet(Single.java:2001)
	at io.github.mzattera.test.Test$HuggingFaceClient.callApi(Test.java:118)

Below the (Maven) dependencies to run the code.

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

		<!-- Java version -->
		<maven.compiler.source>11</maven.compiler.source>
		<maven.compiler.target>11</maven.compiler.target>

		<!-- Library versions -->
		<jackson.version>2.14.2</jackson.version>
		<retrofit.version>2.9.0</retrofit.version>
	</properties>
	<dependencies>
		<!-- Retrofit (create Java HTTP client from REST APIs) -->
		<dependency>
			<groupId>com.squareup.retrofit2</groupId>
			<artifactId>retrofit</artifactId>
			<version>${retrofit.version}</version>
		</dependency>
		<dependency>
			<groupId>com.squareup.retrofit2</groupId>
			<artifactId>adapter-rxjava2</artifactId>
			<version>${retrofit.version}</version>
		</dependency>
		<dependency>
			<groupId>com.squareup.retrofit2</groupId>
			<artifactId>converter-jackson</artifactId>
			<version>${retrofit.version}</version>
		</dependency>

		<!-- Jackson (JSON annotations and bindings) -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.version}</version>
		</dependency>
		<!--
		https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.14</version>
		</dependency>
	</dependencies>

mzattera avatar Jun 05 '23 06:06 mzattera

I have uploaded a small Eclipse project with the code here.

mzattera avatar Jun 26 '23 12:06 mzattera

Is the website still functioning? I downloaded the Eclipse project and the API returns 400 in either case. Same output using curl.

---[Apache HtttpClient with URL: https://by62y2zqbeqalfay.eu-west-1.aws.endpoints.huggingface.cloud]------------
POST https://by62y2zqbeqalfay.eu-west-1.aws.endpoints.huggingface.cloud/ HTTP/1.1
Authorization: Bearer public-endpoint-no-key-needed
Content-Type: application/json
[Content-Type: application/json; charset=UTF-8,Content-Length: 30,Chunked: false]
{"inputs":["Alan Turing was"]}
HTTP/1.1 400 Bad Request
---------------
{
  "error" : "400: Invalid state"
}

I think I have seen this before but cannot remember what I did as a workaround.

drewd avatar May 03 '24 19:05 drewd