測試場景
使用Nginx代理SpringBoot應用,版本如下:
SpringBoot 2.1.3.RELEASE(內嵌tomcat9)
nginx-1.14.0
配置如下:
upstream code_server_pool{
server 127.0.0.1:63049 weight=10;
}
server{
listen 80;
server_name www.pbteach.com;
#驗證碼
location ^~ /checkcode/ {
proxy_pass http://code_server_pool/checkcode/;
}
...
使用postman測試報錯
查看日誌:
nginx日誌:127.0.0.1 - - [08/May/2020:22:57:55 +0800] “POST /checkcode/getToken HTTP/1.1” 400 812 “-” “PostmanRuntime/7.1.1”
SpringBoot日誌如下:
java.lang.IllegalArgumentException: The character [_] is never valid in a domain name.
at org.apache.tomcat.util.http.parser.HttpParser$DomainParseState.next(HttpParser.java:926)
at org.apache.tomcat.util.http.parser.HttpParser.readHostDomainName(HttpParser.java:822)
at org.apache.tomcat.util.http.parser.Host.parse(Host.java:71)
at org.apache.tomcat.util.http.parser.Host.parse(Host.java:45)
at org.apache.coyote.AbstractProcessor.parseHost(AbstractProcessor.java:288)
at org.apache.coyote.http11.Http11Processor.prepareRequest(Http11Processor.java:809)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:384)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
分析與解決
根據SpringBoot的報錯得知,下劃線字符“_”在域名中無效。
查看org.apache.tomcat.util.http.parser.HttpParser源碼:
public DomainParseState next(int c) {
if (HttpParser.isAlpha(c)) {
return ALPHA;
} else if (HttpParser.isNumeric(c)) {
return NUMERIC;
} else if (c == '.') {
if (allowsPeriod) {
return PERIOD;
} else {
throw new IllegalArgumentException(sm.getString(errorMsg,
Character.toString((char) c)));
}
} else if (c == ':') {
if (allowsEnd) {
return COLON;
} else {
throw new IllegalArgumentException(sm.getString(errorMsg,
Character.toString((char) c)));
}
} else if (c == -1) {
if (allowsEnd) {
return END;
} else {
throw new IllegalArgumentException(
sm.getString("http.invalidSegmentEndState", this.name()));
}
} else if (c == '-') {
if (allowsHyphen) {
return HYPHEN;
} else {
throw new IllegalArgumentException(sm.getString(errorMsg,
Character.toString((char) c)));
}
} else {
throw new IllegalArgumentException(sm.getString(
"http.illegalCharacterDomain", Character.toString((char) c)));
}
早期使用SpringBoot低版本時沒有此問題,升級SpringBoot後,內嵌的是Tomcat9版本,對域名的合法性進行校驗中,包含下劃線“_”則拋出異常。
修改nginx配置,將code_server_pool中的下劃線去掉,修改如下:
upstream codeserverpool{
server 127.0.0.1:63049 weight=10;
}
server{
listen 80;
server_name www.pbteach.com;
#驗證碼
location ^~ /checkcode/ {
proxy_pass http://codeserverpool/checkcode/;
}
...
重啓nginx解決此問題。