我需要编写一个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