Exception Groovy HttpBuilder与Cookie的问题
我需要编写一个web客户端,它可以点击传统web应用程序,登录到它,从Exception Groovy HttpBuilder与Cookie的问题,exception,cookies,groovy,httpresponse,httpbuilder,Exception,Cookies,Groovy,Httpresponse,Httpbuilder,我需要编写一个web客户端,它可以点击传统web应用程序,登录到它,从/widget页面中提取一些信息,并根据该页面的HTML进行一些工作。我选择使用Groovy/解决方案,原因超出了这个问题的范围 唯一的缺点(据我所知)是HttpBuilder不支持在请求之间保留cookie。这是一个主要问题,因为(Java)web应用程序使用JSESSIONIDcookies来确定用户是否登录、是否拥有权限等 因此,首先,如果我上面的断言不正确,并且HttpBuilder确实支持跨请求保留cookie,请纠
/widget
页面中提取一些信息,并根据该页面的HTML进行一些工作。我选择使用Groovy/解决方案,原因超出了这个问题的范围
唯一的缺点(据我所知)是HttpBuilder不支持在请求之间保留cookie。这是一个主要问题,因为(Java)web应用程序使用JSESSIONID
cookies来确定用户是否登录、是否拥有权限等
因此,首先,如果我上面的断言不正确,并且HttpBuilder确实支持跨请求保留cookie,请纠正我,也许这里的答案是一个解决方案,它向我展示了如何利用HttpBuilder的这一部分。在这种情况下,我下面的所有代码都是没有意义的
假设我是正确的,而这不是由HttpBuilder处理的,我发现由于某种原因我无法工作,因此我提出了这个问题
我对该代码的修改(见上面的链接)如下:
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
}
}
CookieRetainingHttpBuilder:20
这一行来自请求
:
httpBuilder.request(method, contentType) { request ->
有人知道我为什么会这样吗?此外,我想确认我在TaskAutomater#doWork(…)
方法中的方法/策略是我使用的CookiiereTainingHttpBuilder
“正确”,意思是我:
或者有没有其他更好/更高效的方法来使用HttpBuilder(请记住,
CookiiereTainingHttpBuilder
毕竟只是HttpBuilder的包装器)。我认为,错误可能是由于缺少导入,或者可能是因为HttpBuilder的旧版本。查看HttpBuilder.Class,我看到了以下内容,这为我的建议提供了依据:
protected java.lang.Object parseResponse(org.apache.http.HttpResponse resp, java.lang.Object contentType) throws groovyx.net.http.HttpResponseException { /* compiled code */ }
我相当确定您可以在httpBuilder设置中使用头文件。'Set-Cookie
。语法与您的不同,但变化很小且简单,这是我在使用HttpBuilder时使用的基本方法
@Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7)
import groovyx.net.http.HTTPBuilder
import org.apache.http.HttpException
import static groovyx.net.http.ContentType.TEXT
import static groovyx.net.http.Method.GET
def http = new HTTPBuilder(urlToHit)
http.request(urlToHit, GET, TEXT) { req ->
headers.'User-Agent' = ${userAgent}
headers.'Set-Cookie' = "${myCookie}"
response.success = { resp, reader ->
html = reader.getText()
}
response.failure = { resp, reader ->
System.err.println "Failure response: ${resp.status}"
throw new HttpException()
}
}
另外需要注意的是,您没有故障处理。我不知道这是否会引起一个例外,但它可能值得研究
编辑
正如建议的那样,我正在合并我的答案(谢谢你让我知道……我不确定什么是正确的礼仪)
这是我想到的。我尽了最大努力重用你发布的代码。我尽我所能发表评论。如果你有任何问题,请告诉我
@Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7')
import static groovyx.net.http.ContentType.HTML
import static groovyx.net.http.Method.POST
import static groovyx.net.http.Method.GET
import groovyx.net.http.ContentType
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.URIBuilder
import groovyx.net.http.Method
import org.apache.http.HttpException
/**
* This class defines the methods used for getting and using cookies
* @param baseUrl The URL we will use to make HTTP requests. In this example, it is https://www.pinterest.com
*/
class CookieRetainingHttpBuilder {
String baseUrl
/**
* This method makes an http request and adds cookies to the array list for later use
* @param method The method used to make the http request. In this example, we use GET and POST
* @param contentType The content type we are requesting. In this example, we are getting HTML
* @param url The URI path for the appropriate page. For example, /login/ is for the login page
* @param params The URI query used for setting parameters. In this example, we are using login credentials
*/
public request (Method method, ContentType contentType, String url, Map<String, Serializable> params) {
List<String> cookies = new ArrayList<>()
def http = new HTTPBuilder(baseUrl)
http.request(baseUrl, method, contentType) { req ->
URIBuilder uriBuilder = new URIBuilder(baseUrl)
uriBuilder.query = params
uriBuilder.path = url
headers.'Accept' = HTML
headers.'User-Agent' = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36"
headers.'Set-Cookie' = cookies.join(";")
response.success = { resp, reader ->
resp.getHeaders('Set-Cookie').each {
def cookie = it.value.split(";").toString()
cookies.add(cookie)
}
return reader
}
response.failure = { resp, reader ->
System.err.println "Failure response: ${resp.status}"
throw new HttpException()
}
}
}
}
/**
* This class contains the method to make HTTP requests in the proper sequence
* @param base The base URL
* @param user The username of the site being logged in to
* @param pass The password for the username
*/
class TaskAutomator {
private static String base = "http://myapp.example.com"
private static String user = "thisIsMyUser"
private static String pass = "thisIsMyPassword"
/**
* This method contains the functions in proper order to set cookies and login to a site
* @return response Returns the HTML from the final GET request
*/
static String doWork () {
CookieHandler.setDefault(new CookieManager());
CookieRetainingHttpBuilder cookiedBuilder = new CookieRetainingHttpBuilder(baseUrl: base)
Map logins = [username: user, password: pass]
// 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(GET, 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(POST, HTML, "/login/", 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(GET, HTML, "/", null)
// Test to make sure the response is what I think it is.
return response
// TODO: Now actually do work based off the response.
}
}
TaskAutomator tasker = new TaskAutomator()
String result = tasker.doWork()
println result
@Grab(组='org.codehaus.groovy.modules.httpbuilder',模块='httpbuilder',版本='0.7')
导入静态groovyx.net.http.ContentType.HTML
导入静态groovyx.net.http.Method.POST
导入静态groovyx.net.http.Method.GET
导入groovyx.net.http.ContentType
导入groovyx.net.http.HTTPBuilder
导入groovyx.net.http.URIBuilder
导入groovyx.net.http.Method
导入org.apache.http.HttpException
/**
*此类定义用于获取和使用cookie的方法
*@param baseUrl我们将用于发出HTTP请求的URL。在本例中,它是https://www.pinterest.com
*/
类CookiiereTainingHttpBuilder{
字符串baseUrl
/**
*此方法发出http请求并将Cookie添加到阵列列表中以供以后使用
*@param method用于发出http请求的方法。在本例中,我们使用GET和POST
*@param contentType我们请求的内容类型。在本例中,我们得到的是HTML
*@param url相应页面的URI路径。例如,/login/表示登录页面
*@param params用于设置参数的URI查询。在本例中,我们使用的是登录凭据
*/
公共请求(方法、ContentType、字符串url、映射参数){
列表cookies=newarraylist()
def http=新的HTTPBuilder(baseUrl)
请求(baseUrl、方法、contentType){req->
URIBuilder URIBuilder=新的URIBuilder(baseUrl)
uriBuilder.query=params
uriBuilder.path=url
headers.'Accept'=HTML
headers.'User-Agent'=“Mozilla/5.0(Windows NT 6.3;Win64;x64)AppleWebKit/537.36(KHTML,如Gecko)Chrome/37.0.2049.0 Safari/537.36”
headers.'Set-Cookie'=cookies.join(“;”)
response.success={resp,reader->
相应的getHeaders('Set-Cookie')。每个{
def cookie=it.value.split(“;”).toString()
cookies.add(cookie)
}
回传读取器
}
response.failure={resp,reader->
System.err.println“故障响应:${resp.status}”
抛出新的HttpException()
}
}
}
}
/**
*此类包含按正确顺序发出HTTP请求的方法
*@param base基本URL
*@param user登录到的站点的用户名
*@param传递用户名的密码
*/
类任务自动机{
私有静态字符串基=”http://myapp.example.com"
私有静态字符串user=“thismyuser”
私有静态字符串pass=“thismypassword”
/**
*此方法包含按正确顺序设置cookie和登录站点的函数
*@return response返回最终GET请求的HTML
*/
静态字符串定位销(){
setDefault(新的CookieManager());
CookiiereTainingHttpBuilder cookiedBuilder=新CookiiereTainingHttpBuilder(baseUrl:base)
地图登录=[用户名:用户,密码:通过]
//转到主页,我们将返回登录屏幕的HTML。
//我们并不真正关心这里的响应,只要它是HTTP200。
请求(GET,HTML,“,null)
//登录到该应用程序,成功后,我们将返回HTML以供下载
//“主菜单”屏幕u
@Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7')
import static groovyx.net.http.ContentType.HTML
import static groovyx.net.http.Method.POST
import static groovyx.net.http.Method.GET
import groovyx.net.http.ContentType
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.URIBuilder
import groovyx.net.http.Method
import org.apache.http.HttpException
/**
* This class defines the methods used for getting and using cookies
* @param baseUrl The URL we will use to make HTTP requests. In this example, it is https://www.pinterest.com
*/
class CookieRetainingHttpBuilder {
String baseUrl
/**
* This method makes an http request and adds cookies to the array list for later use
* @param method The method used to make the http request. In this example, we use GET and POST
* @param contentType The content type we are requesting. In this example, we are getting HTML
* @param url The URI path for the appropriate page. For example, /login/ is for the login page
* @param params The URI query used for setting parameters. In this example, we are using login credentials
*/
public request (Method method, ContentType contentType, String url, Map<String, Serializable> params) {
List<String> cookies = new ArrayList<>()
def http = new HTTPBuilder(baseUrl)
http.request(baseUrl, method, contentType) { req ->
URIBuilder uriBuilder = new URIBuilder(baseUrl)
uriBuilder.query = params
uriBuilder.path = url
headers.'Accept' = HTML
headers.'User-Agent' = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36"
headers.'Set-Cookie' = cookies.join(";")
response.success = { resp, reader ->
resp.getHeaders('Set-Cookie').each {
def cookie = it.value.split(";").toString()
cookies.add(cookie)
}
return reader
}
response.failure = { resp, reader ->
System.err.println "Failure response: ${resp.status}"
throw new HttpException()
}
}
}
}
/**
* This class contains the method to make HTTP requests in the proper sequence
* @param base The base URL
* @param user The username of the site being logged in to
* @param pass The password for the username
*/
class TaskAutomator {
private static String base = "http://myapp.example.com"
private static String user = "thisIsMyUser"
private static String pass = "thisIsMyPassword"
/**
* This method contains the functions in proper order to set cookies and login to a site
* @return response Returns the HTML from the final GET request
*/
static String doWork () {
CookieHandler.setDefault(new CookieManager());
CookieRetainingHttpBuilder cookiedBuilder = new CookieRetainingHttpBuilder(baseUrl: base)
Map logins = [username: user, password: pass]
// 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(GET, 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(POST, HTML, "/login/", 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(GET, HTML, "/", null)
// Test to make sure the response is what I think it is.
return response
// TODO: Now actually do work based off the response.
}
}
TaskAutomator tasker = new TaskAutomator()
String result = tasker.doWork()
println result