tencent cloud

边缘安全加速平台 EO

动态与公告
产品动态
安全公告
产品公告
产品简介
产品概述
产品优势
应用场景
EdgeOne 与 CDN 等产品功能对比
使用限制
购买指南
试用套餐体验权益说明
免费版套餐使用说明
计费概述
计费项目
购买指引
续费指引
欠费与退款说明
套餐选型对比
关于“干净流量”计费说明
DDoS 防护容量说明
快速入门
选择业务场景
快速接入网站安全加速
通过 Pages 快速部署网站
域名服务与源站配置
域名服务
HTTPS 证书
源站配置
站点加速
概述
访问控制
智能加速
缓存配置
文件优化
网络优化
URL 重写
修改头部
修改应答内容
规则引擎
图片与视频处理
单连接下载限速
DDoS 与 Web 防护
概述
DDoS 防护
Web 防护
Bot 管理
API 资产识别(Beta)
边缘函数
概述
快速指引
操作指引
Runtime APIs
示例函数
实践教程
Pages
四层代理
概述
新建四层代理实例
修改四层代理实例配置
停用/删除四层代理实例
批量配置转发规则
获取客户端真实IP
数据分析与日志服务
日志服务
数据分析
告警服务
站点与计费管理
计费管理
站点管理
版本管理
通用策略
通用参考
配置语法
请求与响应行为
国家/地区及对应代码枚举
Terraform
Terraform 简介
安装和配置 Terraform
实践教程
自动预热/清除缓存
防盗刷/盗链实践
HTTPS 相关实践
加速优化
流量调度
数据分析与告警
第三方日志平台集成实践
对象存储类源站(例如:COS)配置实践
跨域响应配置
API 文档
History
Introduction
API Category
Making API Requests
Site APIs
Acceleration Domain Management APIs
Site Acceleration Configuration APIs
Edge Function APIs
Alias Domain APIs
Security Configuration APIs
Layer 4 Application Proxy APIs
Content Management APIs
Data Analysis APIs
Log Service APIs
Billing APIs
Certificate APIs
Origin Protection APIs
Load Balancing APIs
Diagnostic Tool APIs
Custom Response Page APIs
API Security APIs
DNS Record APIs
Content Identifier APIs
Legacy APIs
Ownership APIs
Image and Video Processing APIs
Multi-Channel Security Gateway APIs
Version Management APIs
Data Types
Error Codes
常见问题
产品特性相关问题
DNS 记录相关问题
域名配置相关问题
站点加速相关问题
数据与日志相关问题
安全防护相关问题
源站配置相关问题
排障指南
异常状态码参考
EdgeOne 4XX/5XX 状态码排障指南
520/524状态码排障指南
521/522 状态码排障指南
工具指南
相关协议
Service Level Agreement
源站防护启用特别约定
TEO 政策
隐私协议
数据处理和安全协议
联系我们
词汇表

推送至 HTTP 服务器

PDF
聚焦模式
字号
最后更新时间: 2025-07-28 14:41:28
EdgeOne 实时日志推送支持将日志推送至自定义接口地址,您可通过控制台或 API 进行配置。EdgeOne 可通过 HTTP POST 请求调用您提供的后端接口地址,将日志在 HTTP Body 中传输到您指定的服务器上。

操作步骤

1. 登录 边缘安全加速平台 EO 控制台,在左侧菜单栏中,进入服务总览,单击网站安全加速内需配置的站点。
2. 在站点详情页面,单击日志服务 > 实时日志。
3. 在实时日志页面,单击新建推送任务。
4. 在选择日志源页面,填写任务名称、选择日志类型、服务区域、需推送日志的域名/四层代理实例/边缘函数,单击下一步
5. 在定义推送内容页面:
(必选)在预设字段列表中勾选需要推送的日志字段;
(可选)添加自定义日志字段,支持从请求头、响应头、Cookie 头中提取指定字段名称的值;
(可选)配置推送日志筛选条件,默认推送全量日志;
(可选)在高级配置中,配置采样比例,默认不开启采样,推送 100% 日志至目的地。
(可选)在高级配置中,配置日志输出格式,默认格式为 JSON Lines。
6. 在选择目的地页面,选择 HTTP 服务(POST),单击下一步
7. 在目的地信息页面,填写相关目的地及参数信息。
参数名称
说明
接口地址
填入您的日志接收接口地址,例如:https://www.example.com/edgeone-logs
内容压缩
为减少日志内容的大小,节约流量开销,您可以通过勾选使用 gzip 压缩日志文件开启内容压缩,EdgeOne 将会使用 gzip 格式压缩日志后再传输日志,并且会增加 HTTP 头部Content-Encoding: gzip来标明压缩格式。
源站鉴权
选择为加密鉴权时,推送日志时将携带鉴权信息供源站进行验证,保证数据来源身份的安全性。鉴权算法见:鉴权算法参考
自定义 HTTP 请求头
添加需要 EdgeOne 发起请求时携带的 HTTP 头部。例如:
通过添加头部 log-source: EdgeOne 来识别日志来源为 EdgeOne。
通过添加头部BatchSize: ${batchSize}来获取每次 POST 请求内推送的日志条数。
说明
若您填写的头部名称为 Content-Type 等 EdgeOne 日志推送默认携带的头部,那么您填写的头部值将覆盖默认值。
8. 单击推送
9. 实时日志推送任务在配置阶段为了校验接口连通性,将向接口地址发送测试数据进行验证,数据格式如下所示:
{ "ClientState": "CH-AH", "EdgeResponseTime": 366, "RequestID": "13515444256055847385", "ClientRegion": "CN", "RemotePort": 443, "RequestHost": "www.tencent.com", "RequestMethod": "GET", "RequestUrlQueryString": "-", "RequestUrl": "/en-us/about.html", "RequestProtocol": "HTTP/2.0", "EdgeServerID": "336d5ebc5436534e61d16e63ddfca327-d41d8cd98f00b204e9800998ecf8427e", "RequestTime": "2022-07-01T02:37:13Z", "EdgeCacheStatus": "-", "EdgeResponseBytes": 39430, "EdgeResponseStatusCode": 200, "ClientIP": "0.0.0.0", "RequestReferer": "https://www.tencent.com/", "RequestUA": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1", "EdgeServerIP": "0.0.0.0", "RequestRange": "0-100/200", "EdgeInternalTime": 334, "RequestBytes": 237 }

相关参考

服务端解析日志代码示例

当您未开启源站鉴权时,可参考以下 Python 代码在服务端解析请求正文中的日志内容。
# 导入Python标准库中的模块
import time # 用于获取当前时间
import gzip # 用于处理gzip压缩的数据
# 从http.server模块导入HTTPServer和BaseHTTPRequestHandler类
from http.server import HTTPServer, BaseHTTPRequestHandler
import json # 用于处理JSON数据格式
# 定义一个继承自BaseHTTPRequestHandler的类,用于处理HTTP请求
class Resquest(BaseHTTPRequestHandler):
# 重写do_POST方法,该方法会在服务器接收到POST请求时被调用
def do_POST(self):
# 打印请求头信息
print(str(self.headers))
# 打印HTTP请求的命令(如POST)
print(self.command)
# 读取请求体内容,根据请求头中的Content-Length字段确定读取的长度
req_datas = self.rfile.read(int(self.headers['content-length']))
try:
# 尝试解码请求体内容并打印
print(req_datas.decode())
except Exception as e:
# 如果解码过程中发生异常,打印异常信息
print(e)
# 检查请求头中是否有Content-Encoding: gzip,如果有,则解压请求体
if self.headers['Content-Encoding'] == 'gzip':
data = gzip.decompress(req_datas)
# 打印解压后的gzip内容
print('---------------decompress gzip content-------------------------')
print(data.decode())
# 检查请求的路径是否为 '/edgeone-logs',如果不是,则返回404错误
if self.path != '/edgeone-logs':
self.send_error(404, "Page not Found!")
return
# 如果请求路径正确,准备响应数据
data = {
'result_code': '1',
'result_desc': 'Success',
'timestamp': int(time.time()) # 响应当前时间戳
}
# 发送HTTP响应状态码200,表示请求成功
self.send_response(200)
# 设置响应头Content-type为application/json
self.send_header('Content-type', 'application/json')
# 结束响应头的发送
self.end_headers()
# 将响应数据以JSON格式写入到响应体中
self.wfile.write(json.dumps(data).encode('utf-8'))
# 检查当前脚本是否作为主程序运行
if __name__ == '__main__':
# 定义服务器监听的地址和端口,您可将9002替换为自定义端口
host = ('', 9002)
# 创建HTTPServer对象,传入监听地址和端口以及处理请求的请求处理器类
server = HTTPServer(host, Resquest)
# 打印服务器启动信息
print("Starting server, listen at: %s:%s" % host)
# 启动服务器,使其持续运行直到外部中断
server.serve_forever()

请求鉴权算法

如果您在推送目的地信息中,源站鉴权内选择了加密签名,可输入您自定义配置 SecretId 和 SecretKey,EdgeOne 将在请求 URL 中增加签名auth_keyaccess_key,签名算法详情如下:
1. 请求 URL 构成
如下所示,请求 URL 将在后携带 auth_keyaccess_key
http://DomainName[:port]/[uri]?auth_key=timestamp-rand-md5hash&access_key=SecretId
参数说明:
timestamp:请求当前时间,使用 Unix 秒级10位时间戳。
rand:随机数。
access_key:用于标识接口请求方的身份,即您所自定义配置的 SecretId。
SecretKey:固定长度 32 位,即您所自定义配置的 SecretKey。
uri:资源标识符,例如:/access_log/post
md5hash:md5hash = md5sum(string_to_sign),其中 string_to_sign ="uri-timestamp-rand-SecretKey"。通过md5算法计算出的验证串,数字0-9和小写英文字母 a-z 混合,固定长度为32个字符。
2. 计算示例
假定填入参数为: 接口地址:https://www.example.com/access_log/post SecretId = YourID SecretKey = YourKey uri = /access_log/post timestamp = 1571587200 rand = 0
string_to_sign = "/access_log/post-1571587200-0-YourKey"
基于该字符串计算出:
md5hash=md5sum("/access_log/post-1571587200-0-YourKey")=1f7ffa7bff8f06bbfbe2ace0f14b7e16
最终推送时的请求 url 为:
https://www.example.com/cdnlog/post?auth_key=1571587200-0-1f7ffa7bff8f06bbfbe2ace0f14b7e16&access_key=YourID
服务端在接收到推送请求后,提取auth_key的值. 对 auth_key 的值进行拆分,获取timestamprandmd5hash。可先检查 timestamp 是否过期,过期时间建议为300s,并基于上述规则拼装加密字符串,利用 SecretKey 拼装出需加密的字符串,加密后与 auth_key 中的 md5hash 值进行比较,相同则说明鉴权通过。
3. 服务端解析鉴权请求代码示例
Python
Golang
import hashlib

from flask import Flask, request

app = Flask(__name__)


def get_rsp(msg, result={}, code=0):
return {
"respCode": code,
"respMsg": msg,
"result": result
}


def get_secret_key(access_key):
return "secret_key"


@app.route("/access_log/post", methods=['POST'])
def access_log():
if request.method == 'POST':
if request.content_type.startswith('application/json'):
current_time_ts, rand_num, md5hash = request.args.get("auth_key").split("-")
# 判断请求时间是否是在有效期内
if time.time() - int(current_time_ts) > 300:
return get_rsp(msg="The request is out of time", code=-1)

access_key = request.args.get("access_key")
# 通过access_key(SecretId)获取secret_key
secret_key = get_secret_key(access_key)
raw_str = "%s-%s-%s-%s" % (request.path, current_time_ts, rand_num, secret_key)
auth_md5hash = hashlib.md5(raw_str.encode("utf-8")).hexdigest()
if auth_md5hash == md5hash:
# 认证通过
if request.headers['content-encoding'] == 'gzip':
# 解压数据
pass
# 数据处理
return get_rsp("ok")
return get_rsp(msg="Please use content_type by application/json", code=-1)
return get_rsp(msg="The request method not find, method == %s" % request.method, code=-1)

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8888, debug=True)

package main

import (
"context"
"crypto/md5"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
)

func main() {
mux := http.NewServeMux()
mux.Handle("/access_log/post", &logHandler{})

server := &http.Server{
Addr: ":5000",
Handler: mux,
}

// 创建系统信号接收器
done := make(chan os.Signal)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-done

if err := server.Shutdown(context.Background()); err != nil {
log.Fatal("Shutdown server:", err)
}
}()

err := server.ListenAndServe()
if err != nil {
if err == http.ErrServerClosed {
log.Print("Server closed under request")
} else {
log.Fatal("Server closed unexpected")
}
}
}

type logHandler struct{}

func (*logHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
query := r.URL.Query()
authKey := query.Get("auth_key")
accessKey := query.Get("access_key")//access_key 即您提供的SecretId
authKeys := strings.Split(authKey, "-")
if len(authKeys) == 3 {
currentTimeTs := authKeys[0]
//进行时间戳有效期判断
RandNum := authKeys[1]
md5Hash := authKeys[2]
secretKey := getSecretKey(accessKey)
authStr := fmt.Sprintf("%s-%s-%s-%s", "/access_log/post", currentTimeTs, RandNum, secretKey)
data := []byte(authStr)
has := md5.Sum(data)
authMd5 := fmt.Sprintf("%x", has) //转换成字符串进行比较
if authMd5 == md5Hash {
// todo 认证成功
if r.Header.Get("Content-Encoding") == "gzip" {
//解压数据
}
//数据处理
}
} else {
//异常处理
}
}
}

// 获取SecretKey
func getSecretKey(accessKey string) string {
if accessKey != "" {
// 通过Access_key(SecretI)获取Secret_Key
return "secret_key"
}
return ""
}



帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈