O blog da AWS
Usando Lambda@Edge para detectar diferentes dispositivos em tempo real com UserAgent
Por Matheus Lima, Consultor, AWS Professional Services
Introdução
Esta função utiliza a integração entre CloudFront e Lambda chamada AWS Lambda@Edge. Ele permite que o código decida dinamicamente qual imagem retornar ao usuário com base no tipo de UserAgent especificado pelo dispositivo. A versão atual suporta 6 tipos diferentes de dispositivos: desktop, tv, tablet, telefone, bot e carro. Para este tutorial será utilizado um bucket S3 como origem, entretanto qualquer origem de uma distribuição CloudFront Web deve ser compatível.
Caso de Uso
Detecção e agrupamento de agentes de usuário do cliente
Você deseja enviar de volta um objeto diferente para o usuário acessando seu site com base no cabeçalho de agente de usuário. Você pode ter várias versões do seu objeto (por exemplo, uma imagem em resoluções diferentes) na borda e, em seguida, você pode selecionar a versão correta da imagem com base em sua correspondência de padrão personalizado na seqüência de caracteres user-agent. Você pode querer considerar critérios adicionais. Por exemplo, você pode examinar um cookie para decidir qual versão da imagem deve ser entregue. Você também poderia considerar o tipo de referrer. Por exemplo, você poderia sempre entregar as imagens de resolução mais baixa para bots. Você pode personalizar esta lógica na borda com base nas suas necessidades de negócios. [0]
Arquitetura AWS
Requisitos AWS
1 Bucket S3 com os diferentes objetos, com diferentes resoluções.
1 Distribuição CloudFront com o bucket S3 predefinido como origem
1 Função Lambda@Edge
Configurando Lambda:
Abaixo seguem os detalhes para configurações da função:
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Blueprint for modifying CloudFront response header implemented in NodeJS.
Resources:
UserAgentCloudFront:
Type: 'AWS::Serverless::Function'
Properties:
Handler: index.handler
Runtime: nodejs4.3-edge
CodeUri: .
Description: >-
Blueprint for modifying CloudFront response header implemented in
NodeJS.
MemorySize: 128
Timeout: 1
Role: 'arn:aws:iam::xxxxxxxx:role/service-role/lambdaedge'
Configurando CloudFront:
Crie uma distribuição Web, defina o bucket S3 como origem e deixe os outros campos como padrão.
Espere que as configurações sejam propagadas:
Configuração do Bucket S3:
Na imagem abaixo, podemos ver um exemplo de como definir a estrutura de pastas no bucket S3.
Ao abrir uma dessas pastas como por exemplo o diretório tv ou phone, iremos encontrar o arquivo image.jpg. Cada “versão” deste arquivo, em cada pasta, possui uma imagem diferente que será retornada(i.e. Requisição HTTP GET), de acordo com o UserAgent informado automaticamente pelo dispositivo do usuário. Lembre-se que o todos os objetos precisam ter o mesmo nome, neste caso image.jpg.
Dependências do Código-Fonte
O código foi desenvolvido em NodeJS e requer a biblioteca open-source device [1]. É importante destacar que esta não é uma biblioteca oficial e não é suportada pela AWS.
Código-Fonte
const device = require('device');
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request
const headers = request.headers
const userAgentString = headers['User-Agent'] && headers['User-Agent'][0] ? headers['User-Agent'][0] : null
console.log(userAgentString)
var userDevice = device(userAgentString)
var devURI = "other"
//console.log(dev)
switch (userDevice.type) {
case "desktop":
devURI = "desktop";
break;
case "tv":
devURI = "tv";
break;
case "tablet":
devURI = "tablet";
break;
case "phone":
devURI = "phone";
break;
case "bot":
devURI = "bot"
break;
case "car":
devURI = "car";
break;
}
request.uri = "/"+devURI+request.uri
console.log(request.uri)
callback(null, event.Records[0].cf.request);
}
Algoritmo
O código espera um JSON como argumento de entrada. CloudFront fornece este documento à função Lambda@Edge quando ocorre um novo evento no CloudFront. Para o propósito deste tutorial, escolhemos o tipo de evento viewer-request:
Exemplo de Evento Teste:
Aqui está um exemplo de um teste que pode ser usado para simular um evento de solicitação viewer-request no Lambda:
{
"Records": [
{
"cf": {
"configuration": {
"distributionId": "EXAMPLE"
},
"request": {
"headers": {
"Host": [
"d123.cf.net"
],
"Cookie": [
"SomeCookie=1; AnotcherOne=A",
"X-Experiment-Name=B"
],
"User-Agent": [
"Mozilla/5.0 (SmartHub; SMART-TV; U; Linux/SmartTV) AppleWebKit/531.2 (KHTML, like Gecko) Web Browser/1.0 SmartTV Safari/531.2+"
]
},
"clientIp": "2001:cdba::3257:9652",
"httpVersion": "2.0",
"uri": "/experiment-pixel.jpg",
"method": "GET"
}
}
}
]
}
Simulando dispositivos de usuário:
Para fins de demonstração, usaremos o User Agent Switcher Chrome Plugin [5]
Simulando dispositivos de usuário:
Para fins de demonstração, usaremos o User Agent Switcher Chrome Plugin [5]
Simulação de Tablet User Agent:
Simulação de Desktop User Agent:
Exemplos de User-Agent
Aqui estão alguns exemplos que você pode usar para simular diferentes tipos de dispositivos:
Samsung SmartTV:
Mozilla/5.0 (SmartHub; SMART-TV; U; Linux/SmartTV) AppleWebKit/531.2 (KHTML, like Gecko) Web Browser/1.0 SmartTV Safari/531.2+
Firefox MacOS:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36
Android Phone:
Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
IPad:
Mozilla/5.0 (iPad; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B466 Safari/600.1.4
Bibliografia:
[0] http://docs.thinkwithwp.com/AmazonCloudFront/latest/DeveloperGuide/use-cases-for-lambda-at-edge.html
[1] https://github.com/rguerreiro/device
[2] http://developer.samsung.com/internet/user-agent-string-format
[3] https://techblog.willshouse.com/2012/01/03/most-common-user-agents/
[4] https://chrome.google.com/webstore/detail/user-agent-switcher-for-g/ffhkkpnppgnfaobgihpdblnhmmbodake
[5] http://useragentswitcher.org/