selenium利用executeScript执行Post

举报
Amrf 发表于 2019/10/18 10:14:41 2019/10/18
【摘要】 问题场景:同事使用htmlunit发送post请求(负载json)请求一个预期json数据,返回始终和预期不一致;问题分析过程:使用httpclient进行post请求,header中直接附加浏览器中的cookie和其他,content-type未设置时http状态500,content-type设置后状态204,初步判断可能是有连接session相关的判断;使用selenium,设置Hea...

问题场景:

同事使用htmlunit发送post请求(负载json)请求一个预期json数据,返回始终和预期不一致;

问题分析过程:

  1. 使用httpclient进行post请求,header中直接附加浏览器中的cookie和其他,content-type未设置时http状态500,content-type设置后状态204,初步判断可能是有连接session相关的判断;

  2. 使用selenium,设置Headless为false,进行目标网站登录操作,然后由于selenium没有直接post的方法,所以使用executeScript发送相关请求

String js= "function getRet(){\r\n" + 
		"	var datas = null;\r\n" + 
		"	XXX.doPost({\r\n" + 
		"		async:false,\r\n" + 
		"		url:'目标地址',\r\n" + 
		"		data:{json负载},\r\n" + 
		"		success : function(datass){\r\n" + 
		"			datas = datass;\r\n" + 
		"		}\r\n" + 
		"	});\r\n" + 
		"	return datas;\r\n" + 
		"}\r\n" + 
		"return getRet();";
Object ret = (Object)jsExecutor.executeScript(js);

结果符合预期

3.同事使用的是htmlunit

由于目标网站的登录会跳转sso域然后返回存在多次重定向,

设置webClient.getOptions().setRedirectEnabled(true);

HtmlPage retPage = button.click();
Thread.sleep(10000);//区别于synchronized (homePage) {homePage.wait(25000);}和client.waitForBackgroundJavaScript(30000)
//由于存在多次重定向,这个等待是必要的
PrintStream originalOut = System.out;
PrintStream fileOut = new PrintStream("./out111.txt");
System.setOut(fileOut);
System.out.println(((HtmlPage) webClient.getCurrentWindow().getEnclosedPage()).asXml());//获取当前页面而不使用前面的Page变量,因为存在多次重定向
System.setOut(originalOut);

经过修改后,第一步的日志结果符合预期,第二步post请求

1.使用htmlunit的post

WebRequest requestSettings = new WebRequest(url, HttpMethod.POST)
requestSettings.setAdditionalHeader("Content-Type","application/json");
requestSettings.setAdditionalHeader("Accept", "application/json");
requestSettings.setRequestBody(param);

由于和登录共用的一个webclient对象,就没必要设置cookie头了;

测试结果,始终返回一个不符合预期的html结果

2.使用executeJavaScript获取,

js最后的return需要修改为JSON.stringify(getRet()),

ScriptResult result = ((HtmlPage) webClient.getCurrentWindow().getEnclosedPage()).executeJavaScript(js);//使用当前页,即登录跳转最终页
Thread.sleep(10000);//需不需要等待,没有测试
Object rt = result.getJavaScriptResult();
fileOut = new PrintStream("./out222.txt");
System.setOut(fileOut);
System.out.println(rt.toString());
System.setOut(originalOut);

结果符合预期

/*-------------------------------------------------------------------------------------------*/

后面我又采用httpclient的方式继续做了测试, 前面说到可能是有连接session相关的判断,那么考虑 登录和post共用一个httpclient和httpcontent,

CloseableHttpClient httpClient = HttpClients.createDefault();
CookieStore cookieStore = new BasicCookieStore();
HttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);
DoLoginD(httpClient,"xxx",Base64.decode("xxxxx"),httpContext);//使用同一个httpclient和httpContext
RequestConfig requestConfig = RequestConfig.custom()
		.setConnectTimeout(2*5000)
		.setConnectionRequestTimeout(2*5000)
		.setSocketTimeout(2*5000)
		.setRedirectsEnabled(true)
		.build();
HttpPost request = new HttpPost(url);
request.setConfig(requestConfig);
request.setHeader("Accept", "application/json, text/plain, */*"); //, text/javascript, */*; q=0.01
request.setHeader("Content-Type","application/json;charset=utf-8");
StringEntity postStr = new StringEntity(postBody,ContentType.APPLICATION_JSON);//这个ContentType.APPLICATION_JSON需要尤为注意,前面204很大程度是这个没设置的问题
request.setEntity(postStr);
HttpResponse response = httpClient.execute(request,httpContext);
if(response.getStatusLine().getStatusCode() == 200){
	 HttpEntity entity = response.getEntity();
 	 if (entity != null) {
         long len = entity.getContentLength();
         if (len != -1 && len < 2048)
             result = EntityUtils.toString(entity);
         else
         {
             StringBuffer sb = new StringBuffer(1024 * 512);
             BufferedReader in = new BufferedReader(
                     new InputStreamReader(entity.getContent(), encoding));
             String line = null;
             while ((line = in.readLine()) != null)
             {
                 sb.append(line);
             }
             result = sb.toString();
         }
         System.out.println("Fetched data length: " + (result.length() / 1000) + " KB");
         EntityUtils.consume(entity);
     }
} else {
	System.out.println("response code"+response.getStatusLine().getStatusCode());
	HttpEntity entity = response.getEntity();
    String test = EntityUtils.toString(entity);
    System.out.println(test);
}

反思:

前面的204的原因应该主要就是ContentType.APPLICATION_JSON未设置导致的;

参考:

https://stackoverflow.com/questions/12059278/how-to-post-json-request-using-apache-httpclient


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。