2016-11-15 29 views
9

我在我的Grails 3.2.2應用程序中進行了集成測試,該應用程序應檢查CORS支持是否可用。當我啓動應用程序並使用類似Paw或Postman的請求時,我在CorsFilter中設置的斷點顯示我的頭文件設置正確。但是,當我這樣做,從一個集成測試使用RestBuilder用下面的代碼相同的請求:在REST服務集成測試中頭部消失

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斷點顯示兩個頭都爲空:

enter image description here

而且奇怪的是當我在RestTemplate中放置一個斷點時,就在請求執行之前,標題在那裏:

enter image description here

我不明白這些標題可以消失。任何想法?

+1

這是值得使用代理(如Fiddler)或Wireshark來捕獲您發送/接收的流量,至少找出哪一方負責。 –

回答

2

我最近在研究這個問題,並且我不知道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 
    } 
} 
+0

不幸的是,似乎HTTPBuilder不支持OPTIONS請求,這看起來完全荒謬。 – Sebastien

+0

即使它沒有解決問題,因爲缺少選項,但它是一個很好的嘗試,所以你得到了賞金。享受十倍的聲譽提升。 :) –

0

假如同樣的問題。經過一番研究,我發現:http://hc.apache.org/,它支持發送'Origin'和選項請求。

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) 
    } 
}