Why http request made with Apache HttpClient5 receives http 404 error if preemptive BASIC authentication used

huangapple go评论70阅读模式
英文:

Why http request made with Apache HttpClient5 receives http 404 error if preemptive BASIC authentication used

问题

您想要翻译的内容如下:

我需要关于描述在此处 的apache http 5客户端示例的帮助。我的目标是与CURL完全相同:

    curl --verbose --user "admin:admin" --data-binary @20200802112010-test.csv  'http://localhost:8080/api/test/write?db=test' --trace-ascii trace.txt

我修改了示例以执行POST而不是GET:

private void _sendFile(File file) throws IOException, URISyntaxException {
		BasicScheme basicScheme = new BasicScheme();

		basicScheme.initPreemptive(new UsernamePasswordCredentials("admin", "admin".toCharArray()));

		HttpClientContext httpClientContext = HttpClientContext.create();

		HttpHost httpHost = new HttpHost("http", "localhost", 8080);

		httpClientContext.resetAuthExchange(httpHost, basicScheme);

		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			FileEntity fileEntity = new FileEntity(file, ContentType.APPLICATION_FORM_URLENCODED);

			HttpPost httpPost = new HttpPost("http://localhost:8080/api/test/write?db=test");

			httpPost.setEntity(fileEntity);

			try (final CloseableHttpResponse httpResponse = httpClient.execute(httpHost, httpPost, httpClientContext)) {
				if (httpResponse.getCode() == 204) {
					return;
				}

				_logger.warn("Unexpected return code {}", httpResponse.getCode());
			}
		}
	}

我的服务器端代码是由JHipster生成的Spring Boot应用程序,处理请求的控制器如下:

@Profile({"dev", "igor"})
@RequestMapping("/api/test")
@RestController
public class DBEndpointSimulatorResource {

	/**
	 * {@code POST  /write} : Simulates file import on INRAE InfluxDB server.
	 *
	 * @param dataBase the database name
	 * @param content the request body
	 *
	 * @return the {@link ResponseEntity} with status {@code 204 (No Content)}
	 * @throws URISyntaxException if the Location URI syntax is incorrect.
	 */
	@PostMapping("/write")
	public ResponseEntity<?> simulateWrite(@RequestParam("db") String dataBase, @RequestBody String content)
		throws URISyntaxException {

		_logger.debug("REST request to process file for: {}", dataBase);

		if (content == null) {
			throw new BadRequestAlertException(
				"A content must not be empty", "DB FILE", "ERROR-SIMULATOR-001");
		}

		final ResponseEntity.HeadersBuilder<?> headersBuilder = ResponseEntity.noContent();

		return headersBuilder.build();
	}

	private final Logger _logger = LoggerFactory.getLogger(DBEndpointSimulatorResource.class);

}
 
执行_sendFile代码后收到HTTP错误404。我为httpclient 5打开了日志记录,它记录了与服务器端的正常连接,服务器端以404响应:

...(中间部分省略)

起初,我认为Spring Boot端的控制器有问题,但我尝试了与cURL相同的请求,最终成功:

...(中间部分省略)

我看到了内容类型方面的差异,其中Apache HttpClient添加了字符编码。现在我想知道:
1. 我是否应该强制使用UTF-8字符编码,如何实现?还是
2. 我的Apache HttpClient POST示例中是否有其他问题?

请告诉我您需要对其中哪些部分进行翻译。

英文:

I need help with apache http 5 client example described here. My goal is to do exactly the same as CURL:

curl --verbose --user &quot;admin:admin&quot; --data-binary @20200802112010-test.csv  &#39;http://localhost:8080/api/test/write?db=test&#39; --trace-ascii trace.txt

I modified example to perform POST instead of GET:

private void _sendFile(File file) throws IOException, URISyntaxException {
		BasicScheme basicScheme = new BasicScheme();

		basicScheme.initPreemptive(new UsernamePasswordCredentials(&quot;admin&quot;, &quot;admin&quot;.toCharArray()));

		HttpClientContext httpClientContext = HttpClientContext.create();

		HttpHost httpHost = new HttpHost(&quot;http&quot;, &quot;localhost&quot;, 8080);

		httpClientContext.resetAuthExchange(httpHost, basicScheme);

		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			FileEntity fileEntity = new FileEntity(file, ContentType.APPLICATION_FORM_URLENCODED);

			HttpPost httpPost = new HttpPost(&quot;http://localhost:8080/api/test/write?db=test&quot;);

			httpPost.setEntity(fileEntity);

			try (final CloseableHttpResponse httpResponse = httpClient.execute(httpHost, httpPost, httpClientContext)) {
				if (httpResponse.getCode() == 204) {
					return;
				}

				_logger.warn(&quot;Unexpected return code {}&quot;, httpResponse.getCode());
			}
		}
	}

My server side code is Spring Boot App generated by JHipster and controller that handles request is this:

@Profile({&quot;dev&quot;, &quot;igor&quot;})
@RequestMapping(&quot;/api/test&quot;)
@RestController
public class DBEndpointSimulatorResource {

	/**
	 * {@code POST  /write} : Simulates file import on INRAE InfluxDB server.
	 *
	 * @param dataBase the database name
	 * @param content the request body
	 *
	 * @return the {@link ResponseEntity} with status {@code 204 (No Content)}
	 * @throws URISyntaxException if the Location URI syntax is incorrect.
	 */
	@PostMapping(&quot;/write&quot;)
	public ResponseEntity&lt;?&gt; simulateWrite(@RequestParam(&quot;db&quot;) String dataBase, @RequestBody String content)
		throws URISyntaxException {

		_logger.debug(&quot;REST request to process file for: {}&quot;, dataBase);

		if (content == null) {
			throw new BadRequestAlertException(
				&quot;A content must not be empty&quot;, &quot;DB FILE&quot;, &quot;ERROR-SIMULATOR-001&quot;);
		}

		final ResponseEntity.HeadersBuilder&lt;?&gt; headersBuilder = ResponseEntity.noContent();

		return headersBuilder.build();
	}

	private final Logger _logger = LoggerFactory.getLogger(DBEndpointSimulatorResource.class);

}

Once executed _sendFile code receives HTTP error 404. I turned on logging for httpclient 5 and it logs out proper connect to server side which responds with 404:

     ex-00000032: target auth state: UNCHALLENGED
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.http.impl.classic.ProtocolExec   : ex-00000032: proxy auth state: UNCHALLENGED
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.http.impl.classic.ConnectExec    : ex-00000032: acquiring connection with route {}-&gt;http://localhost:8080
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.h.i.classic.InternalHttpClient   : ex-00000032: acquiring endpoint (3 MINUTES)
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] h.i.i.PoolingHttpClientConnectionManager : ex-00000032: endpoint lease request (3 MINUTES) [route: {}-&gt;http://localhost:8080][total available: 0; route allocated: 0 of 5; total allocated: 0 of 25]
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] h.i.i.PoolingHttpClientConnectionManager : ex-00000032: endpoint leased [route: {}-&gt;http://localhost:8080][total available: 0; route allocated: 1 of 5; total allocated: 1 of 25]
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] h.i.i.PoolingHttpClientConnectionManager : ex-00000032: acquired ep-00000031
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.h.i.classic.InternalHttpClient   : ex-00000032: acquired endpoint ep-00000031
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.http.impl.classic.ConnectExec    : ex-00000032: opening connection {}-&gt;http://localhost:8080
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.h.i.classic.InternalHttpClient   : ep-00000031: connecting endpoint (3 MINUTES)
2020-08-03 10:01:00.009 DEBUG 95767 --- [ta-scheduling-2] h.i.i.PoolingHttpClientConnectionManager : ep-00000031: connecting endpoint to http://localhost:8080 (3 MINUTES)
2020-08-03 10:01:00.010 DEBUG 95767 --- [ta-scheduling-2] .i.i.DefaultHttpClientConnectionOperator : http-outgoing-49: connecting to localhost/127.0.0.1:8080
2020-08-03 10:01:00.010 DEBUG 95767 --- [ta-scheduling-2] .i.i.DefaultHttpClientConnectionOperator : http-outgoing-49: connection established 127.0.0.1:52473&lt;-&gt;127.0.0.1:8080
2020-08-03 10:01:00.010 DEBUG 95767 --- [ta-scheduling-2] h.i.i.PoolingHttpClientConnectionManager : ep-00000031: connected http-outgoing-49
2020-08-03 10:01:00.010 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.h.i.classic.InternalHttpClient   : ep-00000031: endpoint connected
2020-08-03 10:01:00.010 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.h.impl.classic.MainClientExec    : ex-00000032: executing POST /api/test/write?db=test HTTP/1.1
2020-08-03 10:01:00.010 DEBUG 95767 --- [ta-scheduling-2] o.a.h.c.h.i.classic.InternalHttpClient   : ep-00000031: start execution ex-00000032
2020-08-03 10:01:00.010 DEBUG 95767 --- [ta-scheduling-2] h.i.i.PoolingHttpClientConnectionManager : ep-00000031: executing exchange ex-00000032 over http-outgoing-49
2020-08-03 10:01:00.010 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.headers       : http-outgoing-49 &gt;&gt; POST /api/test/write?db=test HTTP/1.1
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.headers       : http-outgoing-49 &gt;&gt; Accept-Encoding: gzip, x-gzip, deflate
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.headers       : http-outgoing-49 &gt;&gt; Content-Length: 29423
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.headers       : http-outgoing-49 &gt;&gt; Content-Type: application/x-www-form-urlencoded; charset=ISO-8859-1
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.headers       : http-outgoing-49 &gt;&gt; Host: localhost:8080
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.headers       : http-outgoing-49 &gt;&gt; Connection: keep-alive
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.headers       : http-outgoing-49 &gt;&gt; User-Agent: Apache-HttpClient/5.0 (Java/1.8.0_202)
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.headers       : http-outgoing-49 &gt;&gt; Authorization: Basic YWRtaW46YWRtaW4=
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;POST /api/test/write?db=test HTTP/1.1[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;Accept-Encoding: gzip, x-gzip, deflate[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;Content-Length: 29423[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;Content-Type: application/x-www-form-urlencoded; charset=ISO-8859-1[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;Host: localhost:8080[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;Connection: keep-alive[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;User-Agent: Apache-HttpClient/5.0 (Java/1.8.0_202)[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;Authorization: Basic YWRtaW46YWRtaW4=[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;[\r][\n]&quot;
2020-08-03 10:01:00.011 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;pesmic,dat1=MIC,dat2=2136-0000 dat3=&quot;null&quot;,dat4=60,dat5=0,dat6=0,dat7=0,activ=&quot;null&quot; 1554026400000000000[\n]&quot;
2020-08-03 10:01:00.034 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &gt;&gt; &quot;pesmic,dat1=MIC,dat2=2136-0001 dat3=&quot;null&quot;,dat4=40060,dat5=0,dat6=0,dat7=0,activ=&quot;null&quot; 1554530400000000000&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;HTTP/1.1 404 [\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;X-Content-Type-Options: nosniff[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;X-Frame-Options: SAMEORIGIN[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;X-XSS-Protection: 1[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;Set-Cookie: JSESSIONID=AEC03A81AD4A85F68CB94BAF23E784E8; Path=/; HttpOnly[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;Content-Type: text/html;charset=UTF-8[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;Content-Length: 690[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;Date: Mon, 03 Aug 2020 08:01:00 GMT[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;Keep-Alive: timeout=20[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;Connection: keep-alive[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;[\r][\n]&quot;
2020-08-03 10:01:00.037 DEBUG 95767 --- [ta-scheduling-2] org.apache.hc.client5.http.wire          : http-outgoing-49 &lt;&lt; &quot;[\n]&quot;

In the beginning I thought controller at spring boot side is wrong, but I tried same request with cURL it ended with success:

    =&gt; Send header, 236 bytes (0xec)
0000: POST /api/test/write?db=test HTTP/1.1
0027: Host: localhost:8080
003d: Authorization: Basic YWRtaW46YWRtaW4=
0064: User-Agent: curl/7.64.1
007d: Accept: */*
008a: Content-Length: 2689786
00a3: Content-Type: application/x-www-form-urlencoded
00d4: Expect: 100-continue
00ea: 
&lt;= Recv header, 23 bytes (0x17)
0000: HTTP/1.1 100 Continue
&lt;= Recv header, 19 bytes (0x13)
0000: Content-Length: 0
=&gt; Send data, 65536 bytes (0x10000)
== Info: We are completely uploaded and fine
&lt;= Recv header, 25 bytes (0x19)
0000: HTTP/1.1 204 No Content
&lt;= Recv header, 12 bytes (0xc)
0000: Expires: 0

I see difference in content type where apache http client appends character encoding. Now I wonder:

  1. should I force utf8 character encoding and how?? or
  2. something else is wrong in my apache httpclient post example

答案1

得分: 0

以下是翻译好的部分:

问题描述从未在生产环境中发生,只在我的本地开发环境中出现,该环境是MacOSX Catalina。

我很少重新启动我的MacBookPro,似乎是这导致了问题。在重新启动硬件后,问题再也没有发生。

这并不完全是答案,但这是唯一使问题停止的方法:(

英文:

Problem I described never occurred in production, only in my local development environment which is MacOSX Catalina.

I rarely restart my MacBookPro and seems it caused issue. After restarting hardware, issue never happen again.

This is not quite answer but it is only way to inactivate question Why http request made with Apache HttpClient5 receives http 404 error if preemptive BASIC authentication used

huangapple
  • 本文由 发表于 2020年8月3日 16:33:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/63226167.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定