Расшифровываем короткие ссылки Confluence с помощью nginx

Автор: | 05.11.2018

В числе продуктов австралийской компании Atlassian есть Jira Service Desk для организации работы службы поддержки и Confluence для совместной работы над wiki-подобной базой знаний. Особенностью этих продуктов является совместная интеграция между собой, в частности клиентам Jira Service Desk можно читать статьи в Confluence без назначения соответствующей лицензии. Но это работает ровно до тех пор, пока оператор поддержки не пришлёт клиенту короткую ссылку на Confluence в формате https://confluence.example.com/x/UgCZAQ.

И вот тут нас ждёт сюрприз, так как эта ссылка у клиента не откроется. При этом если разрешить к Confluence анонимный доступ, то для гостей такая ссылка работать будет, но для клиентов Jira Service Desk — нет, разработчики Atlassian тут непреклонны. Ошибка известна разработчикам, но исправлять её не торопятся и обходного решения нет: CONFSERVER-55964.

Можно было бы смириться с данной особенностью, но есть проблема — ссылки в формате TinyURL принудительно генерируются при использовании штатной функции «Поделиться этой страницей». А раз так, то придётся самим искать обходной путь. К счастью, формат таких ссылок не является секретом и даже есть статья о том, как их генерировать самостоятельно: How to programmatically generate the tiny link of a Confluence page. Как видно алгоритм там не сложной и обратимый, а значит написать обратную реализацию не составит труда.

Примечание 1. В данной статье подразумевается, что в качестве frontend-сервера для Confluence используется nginx.
Примечание 2. Для расшифровки нам потребуется модуль ngx_http_perl_module, соответственно он должен присутствовать в вашей системе.

Для обратного преобразования короткой ссылки в формате TinyURL в обычную ссылку в формате PageID создадим небольшой модуль tinyurl.pm, в котором выполним обратные преобразования и перенаправим пользователя на соответствующую страницу в Confluence:

package tinyurl;

use nginx;
use MIME::Base64;

use constant URL => '/pages/viewpage.action?pageId=';

sub decode {
	my $r = shift;
	my $id = $r->filename;

	# Transform tiny string to base64 string
	$id =~ s/(.*)\///ge;
	$id .= "A" x (8 - length($id));
	$id =~ tr/-/\//;
	$id =~ tr/_/+/;

	# Convert base64 string to page ID
	$id = decode_base64($id);
	$id = unpack('L', $id);

	# Redirect to page
	$r->status(302);
	$r->header_out('content-length', 0);
	$r->header_out('location', URL . $id);
	$r->send_http_header('text/html');

	return OK;
}

1;
__END__

Внесём изменения в конфигурацию nginx:

load_module "ngx_http_perl_module.so";
…

http {
	perl_require tinyurl.pm;
	…

	server {
		server_name confluence.example.com;
		…

		location /x/ {
			perl tinyurl::decode;
		}
	}
}

После выполнения nginx -s reload за обработку коротких ссылок вместо Confluence будет отвечать nginx и при запросе https://confluence.example.com/x/UgCZAQ любой пользователь будет перенаправлен на https://confluence.example.com/pages/viewpage.action?pageId=26804306.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *