更多示例代码

简介: 这段代码展示了EdgeRoutine的多个功能示例,包括处理不同的请求类型(如hello world、地理位置信息获取、转发请求等)、实现AB测试、多源拼接、预加载、竞速请求、简单边缘侧日志记录、重定向(基于UserAgent和地理位置信息)及拒绝爬虫访问等。每个功能通过独立函数实现,并在主处理函数中根据请求类型调用相应的处理逻辑。具体效果可参考[Yopian的示例](https://www.yopian.com/sitemap/post.xml)。

EdgeRoutine的示例源码

addEventListener("fetch", function(event) {
event.respondWith(_handleRouter(event));
});
async function _handleRouter(event) {
let json = await event.request.json();
if (json) {
let name = json.name代码效果参考:https://www.yopian.com/sitemap/post.xml
switch(name) {
case "helloworld":
return _handleHelloWorld(event);
case "geo":
return _handleGeo(event);
case "fetch":
return _handleFetch(event, json);
case "request":
return _handleRequest(event, json);
case "response":
return _handleResponse(event, json);
// Cases
case "ab-test":
return _handleABTest(event, json);
case "multi-origin":
return _handleMultipleOriginConcate(event, json);
case "prefetch":
return _handlePrefetch(event, json);
case "race":
return _handleRace(event, json);
case "esi":
return _handleESI(event, json);
case "log":
return _handleEdgeLog(event, json);
case "3xx":
return _handleRedirect3XX(event, json);
case "redirect":
return _handleRedirectGeneral(event, json);
case "deny-bot":
return _handleDenyBot(event, json);
case "waf":
return _handleWAF(event, json);
default:
break;
}
}
return new Response(
{ error : "invalid request" },
{
"status" : 403 ,
"statusText" : "Forbidden"
});
}
async function _handleHelloWorld(event) {
return new Response("Hello World!");
}
async function _handleGeo(event) {
const info = event.info;
let remote_addr = info.remote_addr;
let ip_isp_en = info.ip_isp_en;
let ip_city_en = info.ip_city_en;
let ip_region_en = info.ip_region_en;
let ip_country_en = info.ip_country_en;
let scheme = info.scheme;
let detector_device = info.detector_device;
let content = Geo: ${remote_addr}, \ ${ip_isp_en}, \ ${ip_country_en}, \ ${ip_city_en}, \ ${ip_region_en},\ ${scheme}, \ ${detector_device};
return new Response(content);
}
async function _handleFetch(event, json) {
let fetchURL = json.url;
if (fetchURL) {
return await fetch(fetchURL);
}
return fetch("http://default.ialicdn.com");
}
async function _handleRequest(event, json) {
let headers = json.headers;
let body = json.body;
const fetchInit = {
body : body,
headers: headers
};
return fetch("http://default.ialicdn.com", fetchInit);
}
async function _handleResponse(event, json) {
let resp = await fetch("http://default.ialicdn.com");
let headers = json.headers;
for (var k in headers) {
resp.headers.set(k, headers[k]);
}
return resp;
}
/* ================

  • (1) DevOps |
  • =================/
    function _shouldDoABTest(request) {
    // (1) if request's user agent match a certain string
    {
    const ua = request.headers.get("user-agent");
    if (ua && ua.match(/canary-client/)) {
    return true;
    }
    }
    // (2) whether we have special header
    {
    return request.headers.has("x-ab-test");
    }
    }
    async function _handleABTest(event, json) {
    event.request.headers.delete("content-length");
    const fetchInit = {
    method : event.request.method,
    headers: event.request.headers,
    body : "empty"
    };
    if (_shouldDoABTest(event.request)) {
    return fetch("http://default.ialicdn.com/dev", fetchInit);
    } else {
    return fetch("http://default.ialicdn.com", fetchInit);
    }
    }
    /** ==================================
  • (2) Multiple Origin Concatenation |
    ==================================*/
    async function _handleMultipleOriginConcate(event, json) {
    const respInit = {
    headers: event.request.headers,
    body : json.body
    };
    // (1) We try to concate www.alipay.com and www.tmall.com together
    let {readable, writable} = new TransformStream();
    async function controller() {
    let r1 = await fetch("http://www.alipay.com");
    let r2 = await fetch("https://www.tmall.com");
    await r1.body.pipeTo(writable, {preventClose: true});
    await r2.body.pipeTo(writable);
    }
    controller();
    return new Response(readable, respInit);
    }
    /
    ==================================*
  • (3) Precache/Prefetch |
    ==================================*/
    async function _fetchAndIgnore(url) {
    try {
    // Specify cdnProxy flag to make sure the request goes through the CDN
    let resp = await fetch(url);//, {cdnProxy: true});
    // Make sure to ignore the content otherwise the cache may not be valid
    await resp.ignore();
    } catch (e) {
    console.error("invalid URL: %s", url);
    }
    }
    async function _doPrefetchURLAsync(prefetchURL, event) {
    for (const url of prefetchURL) {
    event.waitUntil(_fetchAndIgnore(url));
    }
    }
    async function _handlePrefetch(event, json) {
    {
    const prefetchURL = json.prefetch;
    if (prefetchURL) {
    // Do not await it and let it run in background
    _doPrefetchURLAsync(prefetchURL, event);
    return new Response("Done Prefetch");
    }
    }
    return new Response("Miss Prefetch");
    }
    /
    ==================================*
  • (4) Race
    ==================================*/
    async function _handleRace(event, json) {
    let fetchList = json.fetchList;
    if (fetchList) {
    return Promise.race(fetchList.map((x) => fetch(x)));
    } else {
    return "forget to include fetchList field in your JSON";
    }
    }
    /
    ==================================*
  • (5) Simple ESI
    * ==================================/
    async function _handleESI(request, json) {
    let { readable, writable } = new TransformStream();
    let newResponse = new Response(readable);
    if (!json.esi) {
    return "forget to include template field in your JSON";
    }
    streamTransformBody(new BufferStream(json.esi), writable);
    return newResponse;
    }
    async function handleTemplate(encoder, templateKey) {
    const linkRegex = new RegExp("esi:include.src=@(.)@.*", 'gm');
    let result = linkRegex.exec(templateKey);
    let esi = "unknown";
    if (!result) {
    return encoder.encode(<${templateKey}>);
    }
    if (result[1]) {
    esi = await subRequests(result[1]);
    }
    return encoder.encode(${esi});
    }
    async function subRequests(target){
    const init = {method: 'GET'};
    let response = await fetch(target, init);
    let text = await response.text();
    return text;
    }
    async function streamTransformBody(readable, writable) {
    const startTag = "<".charCodeAt(0);
    const endTag = ">".charCodeAt(0);
    let reader = readable.getReader();
    let writer = writable.getWriter();
    let templateChunks = null;
    while (true) {
    let { done, value } = await reader.read();
    if (done) break;
    while (value.byteLength > 0) {
    if (templateChunks) {
     let end = value.indexOf(endTag);
     if (end === -1) {
       templateChunks.push(value);
       break;
     } else {
       templateChunks.push(value.subarray(0, end));
       await writer.write(await translate(templateChunks));
       templateChunks = null;
       value = value.subarray(end + 1);
     }
    
    }
    let start = value.indexOf(startTag);
    if (start === -1) {
     await writer.write(value);
     break;
    
    } else {
     await writer.write(value.subarray(0, start));
     value = value.subarray(start + 1);
     templateChunks = [];
    
    }
    }
    }
    await writer.close();
    }
    async function translate(chunks) {
    const decoder = new TextDecoder();
    let templateKey = chunks.reduce(
    (accumulator, chunk) =>
    accumulator + decoder.decode(chunk, { stream: true }), "");
    templateKey += decoder.decode();
    return handleTemplate(new TextEncoder(), templateKey);
    }
    /* ==================================
  • (6) Edge side conditional log
    * ==================================/
    async function _doEdgeLog(data, writer) {
    let resp = await fetch("http://default.ialicdn.com/log",
    {
    method : "POST",
    body : data,
    headers: [["content-type", "application/json"]]
    });
    console.log("logged");
    {
    let stream = new BufferStream("++++++++++++++++++++++++++++++\n");
    await stream.pipeTo(writer, {preventClose: true});
    }
    await resp.body.pipeTo(writer);
    }
    async function _handleEdgeLog(event, json) {
    let start= Date.now();
    let resp = await fetch("http://default.ialicdn.com", {
    method : event.request.method,
    headers: event.request.headers,
    body : json.body
    });
    // Get a promise that is fired when we send out everything
    let {readable, writable} = new TransformStream();
    // (1) first let the fetch request's response goes back and then we post
    // the log back as well internally
    let endPromise = resp.body.pipeTo(writable, {preventClose: true});
    // (2) wait for endPromise to be fired to make sure that the body has been
    // piped back to the client, and then we do the log
    event.waitUntil(endPromise.then(
    (v) => {
    let end = Date.now();
    let diff= (end - start);
    try {
     // You have to await your async promise since wait until is not
     // usable currently maybe. User can use wait until only before
     // returning the main request for now
     event.waitUntil(_doEdgeLog(`{ "cost(millisecond)" : ${diff} }`, writable));
    
    } catch (e) {
     console.error(`${e}`);
    
    }
    },
    (v) => {
    writable.abort();
    console.error("failed");
    }));
    console.error("XXXX");
    // return the response back
    return new Response(readable, {
    status: resp.status,
    headers: resp.headers
    });
    }
    /* ==================================
  • (7) redirect-3xx
    ==================================*/
    async function _handleRedirect3XX(event, json) {
    return fetch("http://www.taobao.com", {redirect: "follow"});
    }
    /
    ==================================*
  • (8) redirect
  • (1) UserAgent
  • (2) Geo information
    ==================================*/
    async function _handleRedirectGeneral(event, json) {
    const fetchInit = {
    method : event.request.method,
    body : json.body,
    headers : event.request.headers
    };
    {
    const ua = event.request.headers.get("user-agent");
    if (ua && ua.match(/firefox/i)) {
    return fetch("http://default.ialicdn.com/firefox", fetchInit);
    }
    if (ua && ua.match(/safari/i)) {
    return fetch("http://default.ialicdn.com/safari", fetchInit);
    }
    }
    {
    if (event.info.detect_device && event.info.detect_device.match(/iphone/)) {
    return fetch("http://default.ialicdn.com/iphone", fetchInit);
    }
    }
    return new Response("unknown request", {status: 403});
    }
    /
    ==================================*
  • (9) Deny bot
    ==================================*/
    async function _handleDenyBot(event, json) {
    {
    const ua = event.request.headers.get("user-agent");
    if (ua && ua.match(new RegExp("xxxspider", "i"))) {
    return new Response("Forbidden", {status: 403});
    }
    }
    return fetch("http://default.ialicdn.com");
    }
    /
    ==================================*
  • (10) Simple WAF
    * ==================================/
    async function _handleWAF(event, json) {
    let city = json.city;
    if (event.info.ip_city_en === city) {
    return new Response("Forbidden", {status: 403});
    }
    // back to origin
    return (JSON.stringify(event.info));
    }
相关文章
如何在文档中添加示例代码
【10月更文挑战第17天】在文档中添加示例代码是非常重要的,它可以帮助读者更好地理解和使用所介绍的内容。
|
6月前
|
异构计算
LabVIEW关于USRPRIO的示例代码
LabVIEW关于USRPRIO的示例代码
42 2
|
3月前
|
机器人 测试技术 C++
ModbusCRC16校验 示例代码
本文提供了ModbusCRC16校验的示例代码,包括计算CRC、添加CRC校验位、删除CRC校验位和比较CRC校验位等四种常用函数的实现,以及一个完整的示例代码。这些代码在Ubuntu20.04环境下经过测试并确认有效。示例代码采用C++编写,展示了如何使用这些函数来处理Modbus通信中的数据校验。
73 1
|
4月前
|
API PHP 开发者
​邮件发送API示例代码,AOKSend关于PHP示例代码
**邮件发送API简化了开发中的邮件功能,如自动化通知和营销邮件。常见示例包括SendGrid和Mailgun的Python代码。AOKSend在PHP中的使用示例展示了如何使用Guzzle库发送邮件,其特点包括高可靠性、易于集成和强大功能。通过API,开发者能高效、可靠地发送大规模邮件。**
|
4月前
|
监控 搜索推荐 Java
​邮件群发API,AOKSend关于Java示例代码
AOKSend邮件群发API简化了企业邮件自动化,提高效率,支持个性化内容和实时分析。其优势在于易于集成、高可靠性、丰富功能和详细统计。Java开发者可快速添加依赖,配置API密钥,使用示例代码发送邮件。通过AOKSend,企业能优化邮件策略,提升邮件营销效果。
|
6月前
|
JavaScript 编译器 API
v-pre的作用、使用场景、示例代码
v-pre 指令在 Vue 中的作用主要是`防止编译器解析某个特定的元素及其内容`。这在你想要展示 Vue 模板语法或者 Mustache 标签(例如 {{message}})而不是让 Vue 将其解析为数据绑定时非常有用。`使用 v-pre 指令的内容将会原样显示在页面上,不会进行数据绑定或插值。
|
算法 Java
Java 方法示例代码demo(一)
Java 方法示例代码demo(一)
63 0
|
Java
Java 方法示例代码demo(三)
Java 方法示例代码demo(三)
69 0
|
Java
Java 方法示例代码demo(二)
Java 方法示例代码demo(二)
47 0
Python调用Face++API处理图片并保存到本地
Python调用Face++API处理图片并保存到本地