Skip to content

Commit c154d6a

Browse files
committed
support oss domain
1 parent 3bcfbec commit c154d6a

3 files changed

Lines changed: 92 additions & 51 deletions

File tree

publish.yaml

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ Parameters:
1717
type: object
1818
additionalProperties: false # 不允许增加其他属性
1919
required: # 必填项
20-
- region
2120
- role
22-
- functionName
23-
- bucketName
24-
- sourceUrl
25-
- cron
21+
- origin
22+
- backupOrigin
23+
- cronExpression
2624
properties:
2725
region:
2826
title: 地域
@@ -54,33 +52,50 @@ Parameters:
5452
type: string
5553
default: ''
5654
description: 函数执行时所扮演的角色
55+
x-roleArn:
56+
type: object
57+
name: cdnbackuprole
58+
pattern: '^acs:ram::[0-9]*:role/.*$'
59+
service: fc
60+
description: 应用所属的函数计算服务配置的 role, 请提前创建好对应的 role, 授信函数计算服务, 并配置好 AliyunOSSFullAccess 和 AliyunFCDefaultRolePolicy policy。
61+
authorities:
62+
- AliyunOSSFullAccess
63+
- AliyunFCDefaultRolePolicy
5764
serviceName:
5865
title: 服务名
5966
type: string
60-
default: cdn-appcenter-service
67+
default: cdn-backup-origin
6168
description: 应用的服务名称
6269
functionName:
6370
title: 函数名
6471
type: string
65-
default: cdn-backup-source
72+
default: cdn-backup-origin
6673
description: 应用的函数名称
67-
bucketName:
68-
title: OSS Bucket名字
69-
type: string
70-
default: ''
71-
description: '备源结果存储到指定的OSS Bucket'
72-
sourceUrl:
74+
origin:
7375
title: 源站地址
7476
type: string
75-
default: ''
7677
description: 指定源站地址
77-
warmupDomain:
78+
backupOrigin:
7879
title: 备源地址
7980
type: string
8081
default: ''
81-
description: 备源地址
82-
cron:
82+
description: '仅支持OSS Bucket域名, 例如: fc-layers.oss-cn-hangzhou.aliyuncs.com'
83+
warmupDomain:
84+
title: 预热域名
85+
type: string
86+
description: 抓取源站并预热到CDN节点
87+
# maxFetchLevel:
88+
# title: 最大抓取层级
89+
# type: number
90+
# default: 0
91+
# description: 最大抓取层级
92+
cronExpression:
8393
title: 定时触发时间
8494
type: string
8595
default: '0 0 0 ? * *'
8696
description: 指定定时触发时间
97+
enable:
98+
title: 是否启用任务
99+
type: bool
100+
default: true
101+
description: 是否启用任务

src/code/index.py

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
# -*- coding: utf-8 -*-
22

3-
import logging, os, re, time
4-
import urllib.parse, urllib.request
3+
import logging
4+
import os
5+
import re
6+
import time
7+
import urllib.parse
8+
import urllib.request
59
from functools import reduce
610
import oss2
711
from aliyunsdkcore.client import AcsClient
812
from aliyunsdkcore.request import CommonRequest
913
from aliyunsdkcore.auth.credentials import AccessKeyCredential
10-
from aliyunsdkcore.auth.credentials import StsTokenCredential
14+
from aliyunsdkcore.auth.credentials import StsTokenCredential
1115

1216
LOGGER = logging.getLogger()
1317

@@ -113,9 +117,16 @@ def download_file(src_url, dist_path):
113117
'''
114118

115119

116-
def parse_and_download_page(url):
120+
def parse_and_download_page(url, level):
117121
global downloaded_list
122+
global max_level
118123

124+
# # 达到最大抓取层级,终止递归
125+
if max_level > 0 and level > max_level:
126+
LOGGER.info("max fetch level {0} reached".format(max_level))
127+
return
128+
129+
level += 1
119130
url_dict = parse_url(url)
120131
domain = url_dict['domain']
121132

@@ -154,9 +165,11 @@ def parse_and_download_page(url):
154165
# http://www.baidu/com/static/index.js
155166
# static/js/index.js
156167
if resource_url.startswith('../'):
157-
resource_url = urllib.parse.urljoin(url_dict['full_path'], resource_url)
168+
resource_url = urllib.parse.urljoin(
169+
url_dict['full_path'], resource_url)
158170
elif resource_url.startswith('./'):
159-
resource_url = urllib.parse.urljoin(url_dict['full_path'], resource_url)
171+
resource_url = urllib.parse.urljoin(
172+
url_dict['full_path'], resource_url)
160173
elif resource_url.startswith('//'):
161174
resource_url = 'https:' + resource_url
162175
elif resource_url.startswith('/'):
@@ -189,7 +202,8 @@ def parse_and_download_page(url):
189202

190203
# 递归解析 html/htm/shtml
191204
if resource_url_dict['ext'] in ['html', 'htm', 'shtml']:
192-
parse_and_download_page(resource_url)
205+
LOGGER.info("parse_and_download_page, level {}".format(level))
206+
parse_and_download_page(resource_url, level)
193207

194208
if not os.path.exists(resource_dir):
195209
os.makedirs(resource_dir)
@@ -219,11 +233,14 @@ def handler(event, context):
219233
global downloaded_list
220234
downloaded_list = []
221235

236+
global max_level
237+
max_level = int(os.environ['MAX_FETCH_LEVEL'])
238+
222239
# 备份源站(域名入口)
223240
# url = 'http://www.cgbchina.com.cn/index.html'
224241
# url = 'http://www.peersafe.cn/index.html'
225-
url = os.environ['SOURCE_URL']
226-
parse_and_download_page(url)
242+
url = os.environ['ORIGIN']
243+
parse_and_download_page(url, 0)
227244
LOGGER.info('总共下载了 %d 个资源' % len(downloaded_list))
228245

229246
# 解析下载网页后备份和预热
@@ -234,37 +251,51 @@ def handler(event, context):
234251
creds.access_key_secret,
235252
creds.security_token)
236253
# 备份目标到OSS
237-
bucket_name = os.environ['BUCKET_NAME']
238-
endpoint = 'oss-' + context.region + '-internal.aliyuncs.com'
254+
backup_origin = os.environ['BACKUP_ORIGIN']
255+
m = re.search(r'(.*).oss-(.*).aliyuncs.com', backup_origin)
256+
if m is None:
257+
LOGGER.error(
258+
"Backup origin {} is not a valid oss domain".format(backup_origin))
259+
raise ValueError(
260+
"Backup origin {} is not a valid oss domain".format(backup_origin))
261+
262+
bucket_name = m.group(1)
263+
region = m.group(2)
264+
endpoint = 'oss-' + region + '.aliyuncs.com:'
239265
# endpoint = 'oss-cn-hangzhou-internal.aliyuncs.com'
240266
bucket = oss2.Bucket(oss_auth, endpoint, bucket_name)
241267
# backup
242268
for tmp_file in downloaded_list:
243269
# /tmp/www.cgbchina.com.cn/index.html -> www.cgbchina.com.cn/index.html
244270
object_name = tmp_file[5:]
245-
LOGGER.info("start to backup matched file = {}".format(object_name))
246-
bucket.put_object_from_file(object_name, tmp_file)
271+
LOGGER.info(
272+
"start to backup matched file = {}".format(object_name))
273+
if bucket is not None:
274+
bucket.put_object_from_file(object_name, tmp_file)
247275

248276
# 预热目标到CDN域名
249-
if "WARMUP_DOMAIN" in os.environ and os.environ["WARMUP_DOMAIN"] != 'dummy':
277+
if "WARMUP_DOMAIN" in os.environ:
250278
cdn_domain = os.environ["WARMUP_DOMAIN"]
251279
cdn_auth = StsTokenCredential(
252280
creds.access_key_id,
253281
creds.access_key_secret,
254282
creds.security_token)
255-
client = AcsClient(region_id=context.region, credential=cdn_auth)
256-
283+
client = AcsClient(region_id=context.region,
284+
credential=cdn_auth)
285+
257286
request = CommonRequest()
258287
request.set_accept_format('json')
259288
request.set_domain('cdn.aliyuncs.com')
260289
request.set_method('POST')
261-
request.set_protocol_type('https') # https | http
290+
request.set_protocol_type('https') # https | http
262291
request.set_version('2018-05-10')
263292
request.set_action_name('PushObjectCache')
264-
cdn_url = cdn_domain + urllib.parse.urlparse('http://' + object_name).path
293+
cdn_url = cdn_domain + \
294+
urllib.parse.urlparse('http://' + object_name).path
265295
request.add_query_param('ObjectPath', cdn_url)
266-
296+
267297
response = client.do_action(request)
268-
LOGGER.info('PushObjectCache: ' + cdn_url + ', and returned: ' + str(response, encoding = 'utf-8'))
298+
LOGGER.info('PushObjectCache: ' + cdn_url +
299+
', and returned: ' + str(response, encoding='utf-8'))
269300

270-
return 'success'
301+
return dict(download_num=len(downloaded_list), success=True)

src/s.yaml

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
edition: 1.0.0
2-
name: cdn-backup-source
2+
name: cdn-backup-origin
33
access: '{{ access }}'
44

55
vars:
66
region: '{{ region }}'
77
environmentVariables:
8-
SOURCE_URL: '{{ sourceUrl }}'
9-
BUCKET_NAME: '{{ bucketName }}'
10-
#WARMUP_DOMAIN: '{{ warmupDomain }}'
8+
ORIGIN: '{{ origin }}'
9+
BACK_ORIGIN: '{{ backupOrigin }}'
10+
WARMUP_DOMAIN: '{{ warmupDomain }}'
1111
service:
1212
name: '{{ serviceName }}'
1313
internetAccess: true
1414
role: '{{ roleArn }}'
1515
logConfig: auto
16-
cron: '{{ cron }}'
1716

1817
services:
1918
cron_cdn_backup:
@@ -22,24 +21,20 @@ services:
2221
region: ${vars.region}
2322
service: ${vars.service}
2423
function:
24+
name: '{{ functionName }}'
2525
environmentVariables: ${vars.environmentVariables}
2626
handler: index.handler
2727
instanceConcurrency: 1
2828
instanceType: e1
2929
memorySize: 512
3030
runtime: python3
31-
timeout: 6000
32-
name: '{{ functionName }}'
33-
asyncConfiguration:
34-
maxAsyncEventAgeInSeconds: 172800
35-
maxAsyncRetryAttempts: 1
36-
statefulInvocation: false
31+
timeout: 1200
3732
codeUri: ./code
3833
triggers:
3934
- name: cron
4035
type: timer
4136
qualifier: LATEST
4237
config:
4338
payload: ''
44-
cronExpression: 'CRON_TZ=Asia/Shanghai ${vars.cron}'
45-
enable: true
39+
cronExpression: '{{ cronExpression }}'
40+
enable: '{{ enable }}'

0 commit comments

Comments
 (0)