我需要編寫一個Web客戶端,它可以訪問舊版網絡應用,登錄到該網頁,從/widget
頁面提取一些信息,並根據此頁面的HTML做一些工作。我選擇使用Groovy/HttpBuilder解決方案,原因不在此問題範圍之內。Groovy HttpBuilder與餅乾問題
唯一的缺點(從我可以告訴的是)HttpBuilder不支持在請求之間保留cookie。這是一個重大的問題,因爲(Java)的Web應用程序使用JSESSIONID
cookie來確定用戶是否登錄,擁有權限等
因此,首先,如果我上面的說法是不正確的,HttpBuilder 確實支持跨請求保留Cookie,請糾正我,也許這裏的答案是一個解決方案,告訴我如何利用HttpBuilder的這一部分。在這種情況下,我所有的代碼都是沒有意義的。
假設我是正確的,這不是由HttpBuilder處理,我發現this excellent solution,我無法工作出於某種原因,因此我的問題。
我的代碼的調整(見上面的鏈接)如下:
TaskAutomator.groovy
====================
package com.me.myapp.tasker
import groovyx.net.http.ContentType
import groovyx.net.http.Method
class TaskAutomator {
static void main(String[] args) {
TaskAutomator tasker = new TaskAutomator()
String result = tasker.doWork("http://myapp.example.com")
println result
}
String doWork(String baseUrl) {
CookieRetainingHttpBuilder cookiedBuilder = new CookieRetainingHttpBuilder(baseUrl)
Map logins = [username: 'user', password: '12345']
// Go to the main page where we will get back the HTML for a login screen.
// We don't really care about the response here, so long as its HTTP 200.
cookiedBuilder.request(Method.GET, ContentType.HTML, "", null)
// Log in to the app, where, on success, we will get back the HTML for a the
// "Main Menu" screen users see when they log in. We don't really care about
// the response here, so long as its HTTP 200.
cookiedBuilder.request(Method.POST, ContentType.HTML, "/auth", logins)
// Finally, now that our JSESSIONID cookies is authenticated, go to the widget page
// which is what we actually care about interacting with.
def response = cookiedBuilder.request(Method.GET, ContentType.HTML, "/widget", null)
// Test to make sure the response is what I think it is.
print response
String result
// TODO: Now actually do work based off the response.
result
}
}
CookieRetainingHttpBuilder
==========================
package com.me.myapp.tasker
import groovyx.net.http.ContentType
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.HttpResponseDecorator
import groovyx.net.http.Method
class CookieRetainingHttpBuilder {
private String baseUrl
private HTTPBuilder httpBuilder
private List<String> cookies
CookieRetainingHttpBuilder(String baseUrl) {
this.baseUrl = baseUrl
this.httpBuilder = initializeHttpBuilder()
this.cookies = []
}
public def request(Method method, ContentType contentType, String url, Map<String, Serializable> params) {
httpBuilder.request(method, contentType) { request ->
uri.path = url
uri.query = params
headers['Cookie'] = cookies.join(';')
}
}
private HTTPBuilder initializeHttpBuilder() {
def httpBuilder = new HTTPBuilder(baseUrl)
httpBuilder.handler.success = { HttpResponseDecorator resp, reader ->
resp.getHeaders('Set-Cookie').each {
String cookie = it.value.split(';')[0]
cookies.add(cookie)
}
reader
}
httpBuilder
}
}
當我運行這段代碼,我得到了下面的堆棧跟蹤(我已經抹去了非有趣的部分是它的相當大):
Exception in thread "main" groovyx.net.http.HttpResponseException: Not Found
at groovyx.net.http.HTTPBuilder.defaultFailureHandler(HTTPBuilder.java:642)
... (lines omitted for brevity)
at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:494)
... (lines omitted for brevity)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:506)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:425)
at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:374)
at groovyx.net.http.HTTPBuilder$request.call(Unknown Source)
at com.me.myapp.tasker.CookieRetainingHttpBuilder.request(CookieRetainingHttpBuilder.groovy:20)
... (lines omitted for brevity)
at com.me.myapp.tasker.TaskAutomator.doWork(TaskAutomator.groovy:23)
... (lines omitted for brevity)
at com.me.myapp.tasker.TaskAutomator.main(TaskAutomator.groovy:13)
CookieRetainingHttpBuilder:20
是從request
這一行:
httpBuilder.request(method, contentType) { request ->
任何人都可以看到爲什麼我得到這個?此外,我想在TaskAutomater#doWork(...)
方法中確認我的方法/策略。 是在我感覺我使用CookieRetainingHttpBuilder
「糾正」:
- 進入主/登錄頁面
- 發佈登錄creds和登錄
- 將小部件頁
還是有不同的方式來使用HttpBuilder,這裏更好/更高效(記住CookieRetainingHttpBuilder
畢竟只是HttpBuilder的包裝器)。
基於從https://github.com/jgritman/httpbuilder/blob/master/src/main/java/groovyx/net/http/HTTPBuilder.java代碼,你就得到了http請求的一些失敗。我不確定究竟是什麼「未找到」,可能的主持人。您可以捕獲https://github.com/jgritman/httpbuilder/blob/master/src/main/java/groovyx/net/http/HttpResponseException.java並檢查內部。 – Vartlok
即使您決定使用'HttpBuilder',我建議查看[Fluent HttpClient](http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fluent.html) - 查看cookie使用請參閱http://java.dzone.com/tips/fluency-and-control-httpclient – ChrLipp