07月13, 2016

casperjs发送post/get请求,form表单提交的疑惑&原因

casperjs发送post请求

官网接口

To POST some data with utf-8 encoding:

casper.open("http://some.testserver.com/post.php", {
       method: "post",
       headers: {
           "Content-Type": "application/json; charset=utf-8"
       },
       encoding: "utf8", // not enforced by default
       data: {
            "table_flip": "(╯°□°)╯︵ ┻━┻ ",
       }
});

带cookie

/*带cookie发送请求*/
var casper = require("casper").create();
casper.start();

/*更新代码*/
phantom.cookiesEnabled = true;
casper.then(function(){
    phantom.addCookie({
        "name": "thinkjs",
        "value": "******",
        "domain": "westpsk.com"
    });
    casper.thenOpen("http://westpsk.com/admin/api/page",{
        method: "POST",
        data: {
            "title": "description test",
            "pathname": "casperjs_test",
            "is_public": "1",
            "status": "3",
            "type": "1",
            "allow_comment": "1",
            "markdown_content": "hello, it"s the content "
        }
    },function(response){
        if(response.status == 200){
            this.echo("update success");
            var json_string = JSON.parse(this.page.plainText);
            // this.echo(json_string.data.codes);
            require("utils").dump(this.page.content);
        }
    });
});

post请求传递的data内容若需要为Json格式,但是发送的时候不是单纯的key+value形式,那么需要添加Content-Type参数。(thx@minmin排查问题)

casper.thenOpen("http://westpsk.com/api/v2?token=***token***=page&operation=update&ids=3701347013",{
    method: "POST",
    data : {
            "data" : {
                "description": "description test",
                "codes": "<html>test codes</html>"
            },
            "control" : {
                "lock" : 1,
                "version" : 0
            },
            "ext" : {
            }
        },
    headers: {
        "Accept":"application/json",
        "Content-Type":"application/json"
    }
},function(response){
    if(response.status == 200){
        this.echo("update success");
        var json_string = JSON.parse(this.page.plainText);
        // this.echo(json_string.data.codes);
        require("utils").dump(this.page.content);
    }
});

疑惑点

现象

发送form表单时候会出现请求参数带不进去的情况。

  • method为get时,q=11不能传过去,input里的表单数据可以取到。
  • method为post,q=11可以传过去,但是input里的表单数据就取不到了。
<form action="http://so.com?q=11" method="get" target="_blank">
    <input name="tab" value="batch">
    <input name="sina-fr" type="hidden" value="bd">
</form>

经查询发现,浏览器会将表单数据封装为字符串,如name=Google&age=18&qq=123456,然后直接附在表单的 action URL 之后。这两者之间用问号(?)进行分隔。如果GET请求的表单action属性中已经包含参数,浏览器会直接将其过滤掉,再附加form表单数据。

而使用post请求,无法传递url和input内容,可能是接口请求的服务端没有做相应的处理。 (疑问)

对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。Request从几个集合取数据是有顺序的,从前到后的顺序依次是 QueryString,Form,最后是ServerVariables。Request对象按照这样的顺序依次搜索这几个集合中的变量,如果有符合的就中止,后面的就不管了。

因此,GET请求方式的表单的action属性中不能附带任何参数,如果需要附加额外的参数,可以采用如下方式:

  1. 采用POST请求方式,在form中增加属性method="post"即可。
  2. 如果仍然想使用GET请求方式,可以在form表单中添加相应的隐藏文本域,例如:

<input name="method" type="hidden" value="queryUser">

页面通过表单(form)向服务器提交数据的时候有两种形式,一个是POST,另一个是GET。两种的一个区别是GET会直接把数据附加在url的后面,而POST发送的数据放置在http包中。form的action属性就是提交数据的url地址,method属性可以指定是GET或POST。

需要注意的是如果采用GET方式,那么action url中参数都会被丢弃,提交时候只会把form中的数据拼接在url向服务器提交;但是POST的方式则不会这样,它会按照action指定的url进行提交数据,包含url后面跟着的参数和参数值。

问题:

form表单发送请求时,url中带有参数,body中也包含需要传输的参数,那么可以正常传输么?表单提交与单纯的post请求性质是不是一样。

像遇到的不一样的情况,是不是服务端限制了传输方式,服务端获取的时候只验证了get方法,没有验证post方法,导致出现只能取到url中的参数,不能取到input中的参数?

验证:

1.get请求

<div class='form'>
    <form action="post?a=1" method="get" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.get("name");
    let pwd = this.get("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

结果:

即:get请求时,action中a=1这个参数被丢弃掉了,可以得到input的内容。

2.post请求

<div class='form'>
    <form action="post?a=1" method="post" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.post("name");
    let pwd = this.post("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

结果:

即:post请求时,action中a=1这个参数可以取到,input的内容也可以获取到。

3.前端使用post请求,后端处理时使用get请求

<div class='form'>
    <form action="post?a=1" method="post" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.get("name");
    let pwd = this.get("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

即:前端使用post请求,而服务端使用get请求的方式是获取不到input中的内容的,只能拿到action里面的url的内容。

解决

  1. 通过form表单提交和直接使用nodejs提交性质一样。 所以通过post请求,可以获取到url和data参数,之前之所以获取不到,可能是因为服务端没有对post请求做处理,导致只取到了url中参数,并没有获取到请求输入的参数。
  2. 通过post请求的话,若传递的数据格式不是单纯的key+value的形式,那么最好加入'Content-Type': 'application/json'

参考

本文链接:http://westpsk.com/post/a-post-get.html

-- EOF --

Comments