Apache 反向代理将 POST 请求转换为 GET 请求

Apache reverse-proxy transforms POST requests into GET requests

我正在尝试使用 SonarQube 分析来自 Jenkins 作业的代码,但当请求出现 405 错误时,我的作业失败了。 Apache 基本上是将 POST 请求更改为 GET 请求,从而导致作业失败。

这是我的 apache 虚拟主机配置:

 <VirtualHost *:80>

      ServerName public.dev
   Redirect permanent / https://public.dev/

</VirtualHost>

<VirtualHost *:443>
   SSLEngine on
   SSLCertificateFile /etc/httpd/ssl/wildcard_cnp_dev.pem
   SSLCertificateKeyFile /etc/httpd/ssl/wildcard_cnp_dev.key

      ServerName public.dev

   ProxyPass / http://localhost:9000/
   ProxyPassReverse / http://localhost:9000/
   ProxyRequests Off
   ProxyPreserveHost on

   RequestHeader set X-Forwarded-Proto "https"
   RequestHeader set X-Forwarded-Port "443"

   <Proxy *>
      Order allow,deny
      Allow from all
   </Proxy>

   ErrorLog /var/log/httpd/sonar-https-error.log
   LogLevel warn
   CustomLog /var/log/httpd/sonar-https-access.log combined

</VirtualHost>

当作业失败时,我得到这个控制台输出:

INFO: ------------------------------------------------------------------------
INFO: EXECUTION FAILURE
INFO: ------------------------------------------------------------------------
INFO: Total time: 18.627s
INFO: Final Memory: 46M/112M
INFO: ------------------------------------------------------------------------
ERROR: Error during SonarQube Scanner execution
org.sonarqube.ws.client.HttpException: Error 405 on https://public.dev/api/ce/submit?projectKey=java-sonar-runner-simple&projectName=Simple%20Java%20project%20analyzed%20with%20the%20SonarQube%20Runner
    at org.sonarqube.ws.client.BaseResponse.failIfNotSuccessful(BaseResponse.java:32)
    at org.sonar.batch.bootstrap.BatchWsClient.failIfUnauthorized(BatchWsClient.java:96)
    at org.sonar.batch.bootstrap.BatchWsClient.call(BatchWsClient.java:67)
    at org.sonar.batch.report.ReportPublisher.upload(ReportPublisher.java:157)
    at org.sonar.batch.report.ReportPublisher.execute(ReportPublisher.java:116)
    at org.sonar.batch.phases.PhaseExecutor.publishReportJob(PhaseExecutor.java:116)
    at org.sonar.batch.phases.PhaseExecutor.execute(PhaseExecutor.java:106)
    at org.sonar.batch.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:185)
    at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:132)
    at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:117)
    at org.sonar.batch.scan.ProjectScanContainer.scan(ProjectScanContainer.java:243)
    at org.sonar.batch.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:238)
    at org.sonar.batch.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:228)
    at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:132)
    at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:117)
    at org.sonar.batch.task.ScanTask.execute(ScanTask.java:55)
    at org.sonar.batch.task.TaskContainer.doAfterStart(TaskContainer.java:86)
    at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:132)
    at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:117)
    at org.sonar.batch.bootstrap.GlobalContainer.executeTask(GlobalContainer.java:122)
    at org.sonar.batch.bootstrapper.Batch.executeTask(Batch.java:119)
    at org.sonar.runner.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.sonar.runner.impl.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:61)
    at com.sun.proxy.$Proxy0.execute(Unknown Source)
    at org.sonar.runner.api.EmbeddedRunner.doExecute(EmbeddedRunner.java:274)
    at org.sonar.runner.api.EmbeddedRunner.runAnalysis(EmbeddedRunner.java:165)
    at org.sonar.runner.api.EmbeddedRunner.runAnalysis(EmbeddedRunner.java:152)
    at org.sonarsource.scanner.cli.Main.runAnalysis(Main.java:118)
    at org.sonarsource.scanner.cli.Main.execute(Main.java:80)
    at org.sonarsource.scanner.cli.Main.main(Main.java:66)
ERROR: 
ERROR: Re-run SonarQube Scanner using the -X switch to enable full debug logging.
Build step 'Invoke Standalone SonarQube Analysis' marked build as failure
Finished: FAILURE

405 错误是因为 SonarQube 正在接收 GET 请求而不是 POST 请求(正常行为)。我可以在 Apache 和 Sonar 访问日志中看到它:

APACHE
192.168.100.7 - - [01/Feb/2016:09:03:06 -0500] "GET /api/ce/submit?projectKey=java-sonar-runner-simple&projectName=Simple%20Java%20project%20analyzed%20with%20the%20SonarQube%20Runner HTTP/1.1" 405 51 "-" "SonarQubeRunner/2.5.1"

SONAR
127.0.0.1 - - [01/Feb/2016:09:14:08 -0500] "GET /api/ce/submit?projectKey=java-sonar-runner-simple&projectName=Simple%20Java%20project%20analyzed%20with%20the%20SonarQube%20Runner HTTP/1.1" 405 51 "-" "SonarQubeRunner/2.5.1"

这在我不使用 Apache 作为反向代理时有效。 Jenkins 在一台机器上,Apache 和 SonarQube 在另一台机器上。

知道为什么会发生这种情况,或者如何解决它?

如果你想在 Sonar 前面放置一个 Apache 反向代理,然后从 Jenkins 访问它,那么你应该在 URL 中添加一个上下文。在声纳服务器上,编辑您的 sonar.properties 文件并编辑以下 属性 以添加上下文。上下文可以是任何东西...这是我的:

sonar.web.context=/quality

然后在 Apache 中编辑您的代理设置。这是我的:

    ProxyPass /quality http://another-machine:9000/quality keepalive=on
    <Location /quality>
            ProxyPassReverse http://another-machine:9000/quality
    </Location>

希望对您有所帮助。