我正在使用Appengine Blob存储区example,并且工作正常(我修改为使用两个文件,但这不是问题)。但是,当我打开nosurf时,它会给我一个HTTP 400。我正在将csrf token 传递给我的表单。即使我仅上传一个文件,该问题仍然存在。
nosurf适用于其他形式,但只给我带来了有关blobstore文件上传的麻烦。

由于代码很大(这只是带有一些细微调整的示例),因此我将其放在此处:http://play.golang.org/p/SJADmn-WvJ(当然,您无法在此处运行它,因为需要app-engine和nosurf)

代码的一小部分:

const rootTemplateHTML = `
<html><body>
<form action="{{.UpUrl}}" method="POST" enctype="multipart/form-data">
    Upload File: <input type="file" name="file1"><br>
    Upload File: <input type="file" name="file2"><br>
    <input type="hidden" name="csrf_token" value="{{ .Token }}">
    <input type="submit" name="submit" value="Submit">
</form>
</body></html>
`

这不起作用:
    http.Handle("/", nosurf.New(http.HandlerFunc(handleRoot)))
    http.Handle("/upload", nosurf.New(http.HandlerFunc(handleUpload)))
    http.HandleFunc("/serve/", handleServe)

但这有效(无400状态):
    http.HandleFunc("/", handleRoot)
    http.HandleFunc("/serve/", handleServe)
    http.HandleFunc("/upload", handleUpload)

这与nosurfapp-engine有关吗?关于应如何解决此问题的任何建议?

谢谢!

最佳答案

Blobstore上传URL的工作原理是将您的文件上传实际发布到应用程序上的特殊/_ah/...路由,该路由实际上未由您的应用程序处理,但被用作基础结构将数据发送到存储上传处理程序的信号一个内部处理程序,用于实际存储。

您传递给生成上载URL的函数的回调路由是应用程序上的路由,一旦完成,该路由将接收一个请求,该请求不包含文件数据,而是文件元数据(例如文件名)以及传递的任何其他参数请求(例如,重要的是CSRF token )。

但是,您传递的 token 是通过对nosurf.Token(r)的调用生成的,其中r是用户浏览器在生成页面时对您的应用发出的请求。当存储上载处理程序将回调请求发送到您的/upload路由时,nosurf期望发送请求的客户端具有为该客户端生成的有效CSRF token (存储上载处理程序),并根据该期望验证该请求。相反,它将接收为您最初发送给用户的页面(包含表单)生成的CSRF token 。

10-05 23:01