【问题标题】:Headers disappear in integration test on REST service标头在 REST 服务的集成测试中消失
【发布时间】:2017-03-29 09:46:49
【问题描述】:

我在我的 Grails 3.2.2 应用程序中有一个集成测试,应该检查 CORS 支持是否正常运行。当我启动应用程序并使用 Paw 或 Postman 之类的东西来执行请求时,我在 CorsFilter 中设置的断点表明我的标头设置正确。但是,当我使用 RestBuilder 使用以下代码从集成测试中执行相同的请求时:

void "Test request http OPTIONS"() {
    given: "JSON content request"

    when: "OPTIONS are requested"
    def rest = new RestBuilder()
    def optionsUrl = url(path)
    def resp = rest.options(optionsUrl) {
        header 'Origin', 'http://localhost:4200'
        header 'Access-Control-Request-Method', 'GET'
    }

    then: "they are returned"
    resp.status == HttpStatus.SC_OK
    !resp.json
}

CorsFilter 中的断点显示两个头都是空的:

奇怪的是,当我在 RestTemplate 中放置断点时,就在请求执行之前,标头就在那里:

我不明白这些标题是如何消失的。有什么想法吗?

【问题讨论】:

  • 值得使用代理(如 Fiddler)或 Wireshark 来捕获您发送/接收的流量,至少找出应归咎于哪一方。

标签: spring rest grails testing


【解决方案1】:

我最近正在解决这个问题,虽然我不知道 RestBuilder 在哪里抑制 Origin 标头,但我确实想出了一个解决方法来测试 grails 的 CORS 支持是否按配置运行:使用 HTTPBuilder 而不是RestBuilder 来调用服务。

build.gradle 中添加org.codehaus.groovy.modules.http-builder:http-builder:0.7.1 作为testCompile 依赖项并将grails.cors.allowedOrigins 设置为http://localhost 后,以下测试都可以正常工作:

import geb.spock.GebSpec
import grails.test.mixin.integration.Integration
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.HttpResponseException
import groovyx.net.http.Method

@Integration
class ExampleSpec extends GebSpec {
    def 'verify that explicit, allowed origin works'() {
        when:
        def http = new HTTPBuilder("http://localhost:${serverPort}/todo/1")
        def result = http.request(Method.GET, "application/json") { req ->
            headers.'Origin' = "http://localhost"
        }

        then:
        result.id == 1
        result.name == "task 1.1"
    }

    def 'verify that explicit, disallowed origin is disallowed'() {
        when:
        def http = new HTTPBuilder("http://localhost:${serverPort}/todo/1")
        http.request(Method.GET, "application/json") { req ->
            headers.'Origin' = "http://foobar.com"
        }

        then:
        HttpResponseException e = thrown()
        e.statusCode == 403
    }
}

【讨论】:

  • 不幸的是,HTTPBuilder 似乎不支持 OPTIONS 请求,这似乎完全荒谬。
  • 尽管由于缺少 OPTIONS 而不能解决问题,但它仍然是一个很好的尝试,所以你得到了赏金。享受十倍声望提升。 :)
【解决方案2】:

有同样的问题。经过一番研究,我发现:http://hc.apache.org/,它支持发送 'Origin' 和 options 请求。

 import grails.test.mixin.integration.Integration
 import grails.transaction.Rollback
 import groovy.util.logging.Slf4j
 import org.apache.http.client.HttpClient
 import org.apache.http.client.methods.HttpOptions
 import org.apache.http.impl.client.MinimalHttpClient
 import org.apache.http.impl.conn.BasicHttpClientConnectionManager
 import spock.lang.Specification

 @Integration
 @Rollback
 @Slf4j
 class CorsIntegrationSpec  extends Specification {

     def 'call with origin'() {
         when:
         def response = call(["Origin":"test","Content-Type":"application/json"])
         then:
         response != null
         response.getStatusLine().getStatusCode() == 200
         response.containsHeader("Access-Control-Allow-Origin")
         response.containsHeader("Access-Control-Allow-Credentials")
         response.containsHeader("Access-Control-Allow-Headers")
         response.containsHeader("Access-Control-Allow-Methods")
         response.containsHeader("Access-Control-Max-Age")
     }  

     private call (Map<String, String> headers) {
         HttpOptions httpOptions = new HttpOptions("http://localhost:${serverPort}/authz/token")
         headers.each { k,v ->
             httpOptions.setHeader(k,v)
         }
         BasicHttpClientConnectionManager manager = new BasicHttpClientConnectionManager()
         HttpClient client = new MinimalHttpClient(manager)
         return client.execute(httpOptions)
     }
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    • 2015-10-03
    • 2018-11-18
    相关资源
    最近更新 更多