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/