跳转到内容

在User talk:FL.YL.BANxS的话题

SunAfterRain (留言贡献)

閣下寫到以上代碼不支援POST方法,而編輯頁面需要使用POST方法,所以只能檢視不能編輯頁面。,那post方法的代碼是蛤?

FL.YL.BANxS (留言贡献)

当时本来想做POST支持,后来还是自觉遵守了m:NOP,所以写了这句话(意思就是我不提供编辑功能,你们想要可以自己写)

当时还能编辑的,但是现在 Cloudflare 的 IP 段已被全域封禁(Open Proxy),所以已经不需要支持POST方法了。

SunAfterRain (留言贡献)
FL.YL.BANxS (留言贡献)
SunAfterRain (留言贡献)

看不太懂,用閣下給的方式 + 上面的連結搞出了

FL.YL.BANxS (留言贡献)

示例(send是POST发送给服务器的数据,recv是从服务器接收的数据,moreWork是接收到数据后做的事,otherWork是接收到数据前的空闲时间做的事):

/* 同步 */
var reply = await fetch(`https://zh.wikipedia.beta.wmflabs.org${url}`, {
  method: 'POST',
  body: send
})
var recv = reply.body//这行要等到上一行执行完毕后才执行
moreWork()
//因为是同步所以没有办法做otherWork
/* end */

/* 异步 */
fetch(`https://zh.wikipedia.beta.wmflabs.org${url}`, {
  method: 'POST',
  body: send
}).then(reply => {
  var recv = reply.body
  moreWork()
})
otherWork()
/* end */

回复是用event.respondWith(handleRequest(event.request))完成的,所以handleRequest这个函数的返回值会被当成是 Response。如果不改这个设计,就必须同步执行(在 handleRequest函数内做完所有事并返回),不然的话就没东西可以返回,如果不写return就返回undefined,然后undefined就被当成是 Response Object并调用event.respondWith传过去,然后event.respondWith接收到无效值,就报错。

所以如果要用异步的话就把async function handleRequest(request) {这行的上面改成这样,然后在需要的时候调用replyCallback传入Response:

var replyCallback
addEventListener('fetch', event => {
  replyCallback = event.respondWith
  handleRequest(event.request)
})
SunAfterRain (留言贡献)

=> Error 522 - Connection timed out

FL.YL.BANxS (留言贡献)

send是用来比喻“要用POST发送的数据”的,不要照搬(不然就报错ReferenceError),要把它换成一个实际的变量或字符串(比如说body: 'test'会POST发送内容“test”给服务器),如果你是纯粹转发客户端请求的话写成这样就行:

//request变量是handleRequest函数接收的参数
{
  method: request.method,//request的属性method是客户端的HTTP请求方法
  body: request.body//如果request.method == 'POST',这个就是客户端POST请求发送过来的数据。
}


另外,因为没有调用replyCallback函数去返回HTTP回复,所以当然就超时了......

所以,已有的new Response(...)就不需要return了,直接改成调用replyCallback传过去就行,所有用到return的地方都需要改(包括try那边的catch)。

SunAfterRain (留言贡献)

?

FL.YL.BANxS (留言贡献)

因为报错TypeError: Illegal invocation,所以如果要做异步的话就不能有handleRequest这一层,把操作全放到addEventListener的回调哪里才行,我试了一下还是莫名其妙Connection timed out。

不如干脆用同步算了,比如说这个示例:

/**
 * https://********************************.cloudflareworkers.com/
 * https://beta.zhwiki.workers.dev/
 **/
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(req) {
  try{
    var url = (new URL(req.url))
    if(url.protocol != 'https:'){
      url.protocol = 'https:'
      return (new Response('', {status: 301, headers: {'Location': url.href}}))
    }

    var header = (new Headers(req.headers))

    var ua = header.get('User-Agent')
    var ual = ua.toLowerCase()

    var host = url.hostname
    var path = url.pathname

    var argv = url.search

    if(path == '/'){
      return (new Response('', {status: 302, headers: {'Location': '/wiki/'}}))
    }

    if(path == '/w/api.php'){
      return (new Response('Api error', {status: 403, statusText: 'Error : https://beta.zhwiki.workers.dev/ can\'t not use MediaWiki Api'}))
    }

    var res = await fetch(`https://zh.wikipedia.beta.wmflabs.org${path}${argv}`, {
      method : req.method,
      body: req.body
    })
    return (new Response(res.body, {status: res.status, headers: res.headers}))
  } catch(err){
    return (new Response(err, {status: 500}))
  }
}
SunAfterRain (留言贡献)

意思說他異步會出錯?

FL.YL.BANxS (留言贡献)

报错TypeError: Illegal invocation就说明这个函数是上下文敏感的,所以要做异步的话就要保持上下文一致:

addEventListener('fetch', event => {
  handleRequest(event.request, (...args) => event.respondWith.apply(event, args))
})

async function handleRequest(req, replyCallback) {

然而还是Connection timed out,debug:

async function handleRequest(req, replyCallback) {
  replyCallback(new Response('Test'))
  return

能正常输出“Test”(上下文问题解决了),难道是then的回调没有被调用导致超时?但是我在浏览器F12那里测试fetch发现then的回调是会被调用的,那就说明是 Cloudflare Workers 自己没有实现这个。

所以说 JavaScript 是可以异步的,但是 Cloudflare Workers 不行(要用await)。

SunAfterRain (留言贡献)

囧rz............那有可能先把js寫在別處,再調用嗎?

FL.YL.BANxS (留言贡献)

什么意思?如果是函数的话那还是同步的。

另外,应用场景如果不需要并发的话用异步没有优势,用同步也没有劣势。

回复“Help:如何访问维基百科”