使用Cloudflare服务优化图床

cloudflare Jul 15, 2019

使用backblaze-B2搭建自己的图床获取图片地址后,我们发现图片的链接非常难记忆,并且不是我们自己的域名。我们可以通过域名的DNS服务并设置CNAME绑定二级域名到f000.backblazeb2.com,这样就可以通过自定义域名访问图片地址了。

比如img.maojun.xyz/file/test/bar.png。但是又有一个问题,/file/test这个也是固定的,是不是也可以优化下,直接显示为img.maojun.xyz/bar.png,这样就显得清爽多了。我们首先对图片的返回地址做下优化,,我们可以将图床地址绑定成自己的域名。

比如我的图片地址器地址就是img.maojunxyz
同时将默认图片地址后的路径/file/bucketName/foo.png优化缩短为foo.png,这样和图片前缀地址拼接上就是:
img.maojun.xyz/foo.png

绑定自定义图片地址

上一篇文章有提到在自己的域名商那里修改CNAME绑定图片服务地址,但是这里将使用Cloudflare作为DNS的服务商。因为Cloudflare提供了一系列对站长友好的工具,并且可以免费使用。比如CDN,Worker,网站信息统计等功能。当然这一步不是必须的,你可以维持你的DNS服务提供商,这不会对后续的操作有影响。你只需根据下面的步骤作为参考并在DNS服务商处做相应的修改即可。

下面以Cloudflare做为演示:
如果没有Cloudflare账号先注册并登入,Cloudflare的官网地址是Cloudflare,登入后你可以看到如下的界面。

登入界面

使用CloudflareDNS解析服务,首先添加你的域名,点击按钮Add a Site,然后根据提示。将DNS地址修改成Cloudflare提供的地址即可完成绑定解析。

绑定后然后点击自己的域名进入到控制台:

控制台


点击菜单图标DNS,进入DNS控制面板。

点击dd record按钮,在输入框中输入并绑定自己的图片域名到b2服务地址。

绑定域名


填写完成后,点击SAVE按钮保存设置。

等待片刻就可以通过自定义图片域名+后缀访问图片地址了。
前后对比:

https://f000.backblazeb2.com/file/bucketName/foo.png # 老的图片链接
https://img.maojun.xyz/file/bucketName/foo.png # 新的图片键接

配置页面规则

在上面的链接中,访问https://img.maojun.xyz/file/bucketName/foo.png,当bucketName正确匹配我们自己创建的buckets时,可以正常访问到图片链接。
bucketName是其他名称或者不是我们创建的buckets名称时,我们让其跳转到错误页面。

https://img.maojun.xyz/file/bucketName/foo.png # 正确的,提供服务
https://img.maojun.xyz/file/aaaaaaaa/foo.png  # 不正确的,跳转到404页面

可以通过CloudflarePage ruler进行配置。点击域名下的控制面板,点击菜单Page ruler进入服务。

page ruler


点击Create Page Ruler按钮,配置如下信息:

URL Description
https://img.maojun.xyz/file/imgxyz/* Cache Level: Standard
https://img.maojun.xyz/file// Forwarding URL (Status Code: 302 - Temporary Redirect, Url: https://maojun.xyz/404notfound)

上面的配置信息规则为:

  • 当访问https://img.maojun.xyz/file/imgxyz/*时,使用标准缓存。
  • 当访问https://img.maojun.xyz/file/*/*(即除了上面的规则外的地址如:https://img.maojun.xyz/file/abc/*)就302掉转到指定的404页面。
注意上面的规则顺序不能错,如果第二条规则在上面则会拦截所有地址包括https://img.maojun.xyz/file/imgxyz/*

这样当访问的请求不是来自配置的页面放行规则时就会被302跳转到指定的页面。

请输入图片描述

简化图片链接

通过自定义域名绑定后,链接地址比之前要更加直观。但是后面的长路径依然存在,我们可以想办法把它去除,让最终的链接格式如下:

https://img.maojun.xyz/foo.png

我们可以使用Cloudflare提供的Workers服务来重写图片的URL地址,让链接地址更加友好和简洁。Workers是一个边缘计算服务,允许你在Cloudflare全球网络中的边界服务器运行JavaScript代码。开发者可以部署serverless(轻服务) 的应用程序。

workers介绍

免费版:

  • 每天10万次请求
  • 30Workers脚本
  • 运行在200个数据中心
  • 免费的workers.dev二级域名
  • 每次请求最大占用CPU运行时间为10ms
  • 首次请求后最低延迟

Cloudflare的主界面,在右侧位置点击进入Workers服务。

主界面


点击Craate a Workers按钮创建一个新的Workers脚本。

创建workers

Scripe代码框中清除原先代码并粘贴以下内容:

'use strict';
const b2Domain = 'img.domain.com'; // configure this as per instructions above
const b2Bucket = 'bucket-name'; // configure this as per instructions above
const b2UrlPath = `/file/${b2Bucket}/`;
addEventListener('fetch', event => {
	return event.respondWith(fileReq(event));
});

// define the file extensions we wish to add basic access control headers to
const corsFileTypes = ['png', 'jpg', 'gif', 'jpeg', 'webp'];

// backblaze returns some additional headers that are useful for debugging, but unnecessary in production. We can remove these to save some size
const removeHeaders = [
	'x-bz-content-sha1',
	'x-bz-file-id',
	'x-bz-file-name',
	'x-bz-info-src_last_modified_millis',
	'X-Bz-Upload-Timestamp',
	'Expires'
];
const expiration = 31536000; // override browser cache for images - 1 year

// define a function we can re-use to fix headers
const fixHeaders = function(url, status, headers){
	let newHdrs = new Headers(headers);
	// add basic cors headers for images
	if(corsFileTypes.includes(url.pathname.split('.').pop())){
		newHdrs.set('Access-Control-Allow-Origin', '*');
	}
	// override browser cache for files when 200
	if(status === 200){
		newHdrs.set('Cache-Control', "public, max-age=" + expiration);
	}else{
		// only cache other things for 5 minutes
		newHdrs.set('Cache-Control', 'public, max-age=300');
	}
	// set ETag for efficient caching where possible
	const ETag = newHdrs.get('x-bz-content-sha1') || newHdrs.get('x-bz-info-src_last_modified_millis') || newHdrs.get('x-bz-file-id');
	if(ETag){
		newHdrs.set('ETag', ETag);
	}
	// remove unnecessary headers
	removeHeaders.forEach(header => {
		newHdrs.delete(header);
	});
	return newHdrs;
};
async function fileReq(event){
	const cache = caches.default; // Cloudflare edge caching
	const url = new URL(event.request.url);
	if(url.host === b2Domain && !url.pathname.startsWith(b2UrlPath)){
		url.pathname = b2UrlPath + url.pathname;
	}
	let response = await cache.match(url); // try to find match for this request in the edge cache
	if(response){
		// use cache found on Cloudflare edge. Set X-Worker-Cache header for helpful debug
		let newHdrs = fixHeaders(url, response.status, response.headers);
		newHdrs.set('X-Worker-Cache', "true");
		return new Response(response.body, {
			status: response.status,
			statusText: response.statusText,
			headers: newHdrs
		});
	}
	// no cache, fetch image, apply Cloudflare lossless compression
	response = await fetch(url, {cf: {polish: "lossless"}});
	let newHdrs = fixHeaders(url, response.status, response.headers);

  if(response.status === 200){

    response = new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: newHdrs
    });
  }else{
    response = new Response('File not found!', { status: 404 })
  }

	event.waitUntil(cache.put(url, response.clone()));
	return response;
}

注意代码的第2-3行:

const b2Domain = 'img.domain.com'; // configure this as per instructions above
const b2Bucket = 'bucket-name'; // configure this as per instructions above
  • b2Domain:修改成自己图床的域名。
  • b2Bucket,修改成自己的bucket名字。

修改后点击按钮Save and Depoly保存。

workers脚本

保存后还不能直接使用,我们需要配置下规则。

进入域名下的控制面板。点击菜单Workers进入面板,然后点击Add route按钮。

worker route

添加路由为之前配置的图片服务器地址,后面使用*匹配该域名下的所有所有内容。
并在Worker处选择刚才创建的Workers名称。

配置worker路由

配置好少,稍等片刻生效。即可以通过最终的图片地址访问了:

https://img.maojun.xyz/foo.png
注意:配置Workers后上面配置的Page ruler规则会失效。配置了Workers规则会先走。

配置防盗链

可以配置Referer来判断是否是自己的来自自己域名,如果不是则都拦截。
由于Referer是可以修改的,所以这只能简单的进行拦截。

进入域名下的面板,点击菜单Firewall进入服务。

firewall


点击**+ Create firewall rule**进入防火墙规则服务。

创建防火墙

填写规则名称和规则匹配条件:

Field Operator Value
Referer does not contains maojun.xyz
URI Full contains img.maojun.xyz
(not http.referer contains "maojun.xyz" and http.request.full_uri contains "img.maojun.xyz")

上面的规则是:
如果URI全路径中包含了img.maojun.xyz内容,同时Referer不包含maojun.xyz则拦截。
由于这个图床我暂时只有一个域名即maojun.xyz在用,如果你有多个域名使用同一图床,可以在上面的规则中填加多个域名放行。

配置完以上后,就可以通过优化后的图片地址https://img.maojun.xyz/test.png访问了。

(完)

参考链接:
使用 Backblaze B2 和 Cloudflare Workers 搭建可以自定义域名的免费图床
Using Backblaze B2 with the Cloudflare CDN

标签

毛俊

探索,热爱,分享。

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.