扩展:移动前端/配置浏览器自动检测

This page is a translated version of the page Extension:MobileFrontend/Configuring browser auto-detection and the translation is 28% complete.

这个文档解释了站点管理员怎么样自动地启用插件,以便于为使用移动设备访问网站的用户重定向一个移动视图,而不是启用桌面视图。

内置自动检测

从提交5a1867e开始,MobileFrontend支持自动地设备检测,并且仅需要很少的配置。 所有你需要做的事情就是把以下代码:$wgMFAutodetectMobileView = true;放到你的LocalSettings.php的文件中。 当然这是最简单的办法,他的性能也几乎是最低的。 这个解决方案不兼容开启了前端缓存的情况,因为这个方案无法让缓存知道移动视图和桌面视图的区别。

Apache Mobile Filter (AMF)

As of commit 0fb2c72d, MobileFrontend supports the Apache Mobile Filter (AMF) for device detection. 你使用的服务器必须是Apache服务器 按照如下的AMF配置步骤/设置,应该可以让你的需求运行起来。 这个函数和内置自动检测非常相似,并且没有特殊配置的话,也不兼容有前端缓存的方案。

Webserver/proxy-cache device detection

反向代理(如Varnish )可以告诉MediaWiki是否需要使用移动端页面,这样就可以创建对前端缓存友好的自动检测机制。

For Varnish 4.0 or later, replace the keyword remove with unset.

Detection using Varnish: mobile site on another domain

Suppose we use Varnish, and we want wiki.example.com to show desktop version, and m.wiki.example.com to show mobile version. Here is how to do that.

sub vcl_recv {
	remove req.http.x-subdomain; # Requester shouldn't be allowed to supply arbitrary X-Subdomain header
	if (req.http.host == "m.wiki.example.com") { # 移动域名
		set req.http.host = "wiki.example.com"; # 桌面域名
		set req.http.x-subdomain = "m";
	}
}
sub vcl_hash {
	# Cache the mobile version of pages separately.
	#
	# NOTE: x-subdomain header should only have one value (if it exists), therefore vcl_recv() should remove user-supplied X-Subdomain header.
	hash_data(req.http.x-subdomain);
}

LocalSettings.php should contain the following:

$wgMFAutodetectMobileView = false;
$wgMobileUrlCallback = fn ( $domain ) => "m.$domain"; // domain for mobile site
$wgCookieDomain = ".wiki.example.com";

Where "%h<#>" maps to a segment of the hostname of $wgServer. So, if $wgServer = 'en.wikipedia.org';, %h0 is "en", %h1 is "wikipedia", %h2 is "org". Given this, the above $wgMobileUrlTemplate will automatically interpolate your mobile URL as "en.m.wikipedia.org". This is particularly useful for the WMF and projects like Wikipedia, which follow a template of <lang code>.wikipedia.org, so the mobile domain will always look like <lang code>.m.wikipedia.org.

In this solution, built-in autodetection should be disabled ($wgMFAutodetectMobileView = false;), so that MediaWiki wouldn't question the decisions of Varnish.

Detection using Varnish: same domain for desktop/mobile site

Suppose we use Varnish, and we want wiki.example.com to show desktop/mobile version on the very same URLs (without creating additional domains like "m.wiki.example.com", etc.). Here is how to do that.

sub vcl_recv {
	remove req.http.x-subdomain; # Requester shouldn't be allowed to supply arbitrary X-Subdomain header
	if(req.http.User-Agent ~ "(?i)^(lg-|sie-|nec-|lge-|sgh-|pg-)|(mobi|240x240|240x320|320x320|alcatel|android|audiovox|bada|benq|blackberry|cdm-|compal-|docomo|ericsson|hiptop|htc[-_]|huawei|ipod|kddi-|kindle|meego|midp|mitsu|mmp\/|mot-|motor|ngm_|nintendo|opera.m|palm|panasonic|philips|phone|playstation|portalmmm|sagem-|samsung|sanyo|sec-|sendo|sharp|softbank|symbian|teleca|up.browser|webos)") {
		set req.http.x-subdomain = "m";
	}

	if(req.http.Cookie ~ "mf_useformat=") {
		# This means user clicked on Toggle link "Mobile view" in the footer.
		# Inform vcl_hash() that this should be cached as mobile page.
		set req.http.x-subdomain = "m";
	}
}
sub vcl_hash {
	# Cache the mobile version of pages separately.
	#
	# NOTE: x-subdomain header should only have one value (if it exists), therefore vcl_recv() should remove user-supplied X-Subdomain header.
	hash_data(req.http.x-subdomain);
}

LocalSettings.php should contain the following:

$wgMFAutodetectMobileView = true;
$wgCookieDomain = ".wiki.example.com";
In this solution, built-in autodetection should be enabled (it won't impact the cache):
$wgMFAutodetectMobileView = true;

Otherwise MobileFrontend misbehaves (if we don't set $wgMobileUrlCallback, it ignores X-Subdomain header, if we do, it doesn't set "useformat" cookies for "toggle Mobile view" links in the footer").

Detection using nginx: mobile site on another domain

Suppose we use nginx, and we want wiki.example.com to show desktop version, and m.wiki.example.com to show mobile version. Here's how to do that. This configuration mimics the behavior of WMF sites.

# [...]

server_tokens off;
set_real_ip_from localhost;
real_ip_header X-Forwarded-For;

map $cookie_stopMobileRedirect $mobile_redirect {
	default ?01;
	"" ${http_sec_ch_ua_mobile}1;
}

ssl_certificate /path/to/ssl-certificate.pem;
ssl_certificate_key /path/to/ssl-certificate-key.pem;
ssl_dhparam /path/to/ssl-dhparams.pem;

server {
	listen 443 ssl;
	listen [::]:443 ssl;

	root /var/www/html/example;

	index index.php;

	server_name localhost;

	location ~ ^/w/(index|load|api|thumb|opensearch_desc|rest|img_auth)\.php$ {
		include fastcgi_params;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_pass unix:/run/php/php8.1-fpm.sock;
	}

	location /w/images {}

	location /w/images/deleted {
		deny all;
	}

	location ~ ^/w/resources/(assets|lib|src) {
		try_files $uri 404;
		add_header Cache-Control "public" always;
		expires 7d;
	}

	location ~ ^/w/(skins|extensions)/.+\.(css|js|gif|jpg|jpeg|png|svg|wasm|ttf|woff|woff2)$ {
		try_files $uri 404;
		add_header Cache-Control "public" always;
		expires 7d;
	}

	location = /w/images/favicon.svg {
		add_header Cache-Control "public" always;
		expires 7d;
	}

	location = /favicon.ico {
		rewrite ^ /w/images/favicon.ico;
	}

	location = /w/images/favicon.ico {
		add_header Cache-Control "public" always;
		expires 7d;
	}

	location /w/sitemap {}

	location = /sitemap.xml {
		rewrite ^ /w/sitemap/sitemap-index-wiki.xml;
	}

	location ~ ^/w/(COPYING|CREDITS)$ {
		default_type text/plain;
	}

	location /w/rest.php/ {
		try_files $uri $uri/ /w/rest.php?$query_string;
	}

	location /wiki/ {
		rewrite ^/wiki/(?<pagename>.*)$ /w/index.php;
	}

	location = / {
		return 301 /wiki/Main_Page;
	}

	location / {
		return 404;
	}

	error_page 404 /w/images/404.html;

	location /w/images/404.html {
		internal;
	}
}

server {
	listen 80 default_server;
	listen [::]:80 default_server;

	server_name wiki.example.com;

	return 301 https://$host$request_uri;

	return 404;
}

server {
	listen 443 default_server ssl;
	listen [::]:443 default_server ssl;

	server_name wiki.example.com;

	location / {
		if ($arg_mobileaction = toggle_view_desktop) {
			add_header Set-Cookie "stopMobileRedirect=true; Domain=.wiki.example.com; Path=/; Max-Age=2592000; HttpOnly; Secure";
			break;
		}

		if ($mobile_redirect != ?01) {
			return 302 https://m.wiki.example.com$request_uri;
		}

		if ($http_host != wiki.example.com) {
			return 301 https://wiki.example.com$request_uri;
		}

		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass https://localhost;
	}
}

server {
	listen 443 ssl;
	listen [::]:443 ssl;

	server_name m.wiki.example.com;

	location / {
		if ($arg_mobileaction = toggle_view_mobile) {
			add_header Set-Cookie "stopMobileRedirect=; Domain=.wiki.example.com; Path=/; Max-Age=0; HttpOnly; Secure";
		}

		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Subdomain m;
		proxy_pass https://localhost;
	}
}

LocalSettings.php should contain the following:

$wgMFAutodetectMobileView = false;
$wgMobileUrlCallback = fn ( $domain ) => "m.$domain";
$wgCookieDomain = ".wiki.example.com";