分类目录归档: 学习日志

libcurl POST数据大于1024个字节需要注意的问题

    最近在测试libcurl使用代理的功能,发现自己的数据在正常情况下可以post,在使用http代理软件Anon的时候post大于1024个字节时失败了。

尝试其他代理服务器软件又可以,如tinyproxy、kingate,这样只能怀疑是代理服务软件Anon的问题了。

使用IE测163邮箱上传大文件没问题,又怀疑会是否自己代码的问题了。

最后抓包逐一排查发现了这个 Expect: 100-continue 没见过的东西。

谷歌一下得出:

在使用curl做POST的时候, 当要POST的数据大于1024字节的时候, curl并不会直接就发起POST请求, 而是会分为俩步

1. 发送一个请求, 包含一个Expect: 100-continue, 询问Server使用愿意接受数据

2. 接收到Server返回的100-continue应答以后, 才把数据POST给Server

这是libcurl的行为.

具体的RFC相关描述: http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3

于是,这样就有了一个问题, 并不是所有的Server都会正确应答100-continue, 比如lighttpd, 就会返回417 “Expectation Failed”, 则会造成逻辑出错

要解决的办法也挺容易:

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); // Disable Expect: header (lighttpd does not support it)

也就是说Anon代理软件也会出这个问题。

参考:http://www.laruence.com/2011/01/20/1840.html


新blog

隔了差不多一年没写日志

由于因为厌烦了WordPress更新和时不时发现bug,14年初就想用go重写blog。

新blog是在空余时间逼着自己一点一点写起来的。

主题是扒了WordPress的,框架用的是beego。

后台丑的没法看只能用,没有任何css、js纯html。

其他功能以后再一点点慢慢完善吧

go语言的:=运算符

[cpp]
// xxxxxxxxxxxxxxxxxxxxxx project main.go
package main

import (
"fmt"
)

func test() (int, int) {
return 1, 2
}

func main() {

i, j := test()
i, j := test()
fmt.Println("%d %d", i, j)
}
[/cpp]
报错 :15: no new variables on left side of :=
[cpp]
package main

import (
"fmt"
)

func test() (int, int) {
return 1, 2
}

func main() {

i, j := test()
k, j := test()
fmt.Println("%d %d %d", i, j, k)
}
[/cpp]
不报错
貌似说明用了:=后 至少得有一个变量是未知类型的,否则提示没有新的变量在:=的左侧。
//////////////////////////////////////////////////////////////////////////////////////////////////////////
[cpp]
// xxxxxxxxxxxxxxxxxxxxxx project main.go
package main

import (
"fmt"
)

type st struct {
d int
}

func test() (int, int) {
return 1, 2
}

func main() {

var x st
i, j := test()
x.d, j := test()

fmt.Println("%d %d %d", i, j, x.d)
}
[/cpp]
报错 :20: non-name x.d on left side of :=
[cpp]
// xxxxxxxxxxxxxxxxxxxxxx project main.go
package main

import (
"fmt"
)

type st struct {
d int
}

func test() (int, int) {
return 1, 2
}

func main() {

var x st
i, j := test()
x.d, k := test()

fmt.Println("%d %d %d %d", i, j, x.d, k)
}
[/cpp]
报错 :20: non-name x.d on left side of :=
这说明 := 不能给结构体成员赋值?
[cpp]
package main

import (
"fmt"
)

type st struct {
d int
}

func test() (int, int) {
return 1, 2
}

func main() {

var x st
i, j := test()
x.d, j = test()

fmt.Println("%d %d %d", i, j, x.d)
}
[/cpp]
不报错

官方解释 http://golang.org/ref/spec#Short_variable_declarations
Short variable declarations

A short variable declaration uses the syntax:
ShortVarDecl = IdentifierList ":=" ExpressionList .

It is a shorthand for a regular variable declaration with initializer expressions but no types:
"var" IdentifierList = ExpressionList .

i, j := 0, 10
f := func() int { return 7 }
ch := make(chan int)
r, w := os.Pipe(fd) // os.Pipe() returns two values
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate

Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.
field1, offset := nextField(str, 0)
field2, offset := nextField(str, offset) // redeclares offset
a, a := 1, 2 // illegal: double declaration of a or no new variable if a was declared elsewhere

Short variable declarations may appear only inside functions. In some contexts such as the initializers for "if", "for", or "switch" statements, they can be used to declare local temporary variables.

第三四个例子网上也有人讨论 https://groups.google.com/forum/#!msg/golang-nuts/ItYSNKqt_kA/OLGaOoDtCHgJ
感谢 http://v2ex.com/t/87324 里的 wwwjfy