WX LightREST

A classe lrSession

Por definição, um servidor REST é do tipo "Stateless" (sem estado), o que significa que o solicitante deve poder chamar um método sem nenhum contexto prévio (o servidor não mantém entre duas chamadas nenhuma informação persistente referente ao cliente REST).

Não obstante a opinião dos puristas, um certo pragmatismo pode levar a transigir com este princípio de "Stateless" e armazenar no servidor informações contextuais referentes ao cliente (por exemplo, a identidade do usuário, uma seleção de pasta em curso, etc.). Para evitar solicitar ao requisitante que informe sistematicamente essas informações a cada chamada (ou ao código REST de consultar o banco de dados para recuperar cada vez os mesmos dados), é prático armazená-los temporariamente no servidor e fornecer ao cliente REST um ID de sessão que ele poderá usar novamente e assim permitir ao servidor acessar os dados da sessão.

Esta é a razão de ser da classe lrSession, que oferece métodos para:

  • Criar uma sessão
  • Verificar a validade da sessão (não expirada)
  • Armazenar e ler dados da sessão
  • Destruir uma sessão

A classe lrSession implementa os Membros, Constantes e Métodos descritos abaixo.

Membros

Membro Tipo Descrição
ID String Identificador da sessão
SessionsDirectory String Diretório de armazenamento das sessões (por padrão, subdiretório $LR_SESSIONS do executável)

Códigos de Erro

Código de Erro Valor Descrição
ErrorSessionExpired 0x1000 Sessão expirada
ErrorSessionIllegal 0x1001 Sessão ilegal (ID inválido)
ErrorSessionCannotLoad 0x1002 Impossível carregar os dados da Sessão
ErrorSessionCannotSave 0x1003 Impossível salvar os dados da Sessão
ErrorSessionCannotSetValue 0x1004 Impossível memorizar o valor na Sessão
ErrorSessionCannotDestroy 0x1005 Impossível destruir a Sessão
ErrorSessionCannotDecypher 0x1006 Impossível descriptografar os dados da Sessão

Métodos

Check() : (booleano, inteiro)

Verificação da sessão: Assinatura válida e sessão que não excedeu o prazo máximo de inatividade (timeout).

Parâmetros: Nenhum

Retorno:

  • booleano: Validade do ID de sessão
  • inteiro: código de erro

Exemplo:

Procedimento REST com verificação da validade da sessão. O identificador da sessão é passado pelo solicitante em um cabeçalho SESSION_ID da requisição REST.

PROCEDIMENTO REST_TestSession(pRequest é lrRequest) : lrResponse
    oResponse é lrResponse
    oSession é lrSession
    bOK é booleano
    eErro é inteiro
    
    oSession:ID = pRequest::GetHeaderValue("SESSION_ID")
    (bOK, eErro) = oSession:Check()
    
    se bOK então
        oResponse:Body = "A sessão é válida"
        oResponse:Status = lrResponse::StatusOK
    senão
        oResponse:Body = oSession:GetErrorMessage(eErro)
        oResponse:Status = lrResponse::StatusUnauthorized //Status HTTP 401
    fim
    
    oResponse:ContentType = lrResponse::ContentTXT
    RETORNA oResponse

Create(Timeout) : booleano

Criação de uma nova sessão, com expiração automática quando o período de inatividade ultrapassar o parâmetro Timeout. A identificação da sessão inclui uma assinatura que permite detectar o uso de um ID "manipulado" e, portanto, identificar um usuário suspeito (que poderá ser bloqueado com seu endereço IP, por exemplo).

Parâmetro Tipo Descrição
Timeout Inteiro Duração máxima de inatividade da sessão, em Minutos. Após expiração, esta será automaticamente destruída

Retorno: Booleano. Verdadeiro se a sessão foi criada, Falso se falhou (neste caso, a função ErroInfo() informará o motivo).

Exemplo:

Criação de uma nova sessão que expira após 600 segundos de inatividade. Retorna-se o ID de sessão no cabeçalho HTTP da resposta. O solicitante poderá apresentar este ID em chamadas REST subsequentes.

PROCEDIMENTO REST_CreateSession(pRequest é lrRequest) : lrResponse
    oSession é lrSession
    oResponse é lrResponse
    
    SE NÃO oSession:Create(600) ENTÃO
        oResponse:Status = lrResponse::StatusInternalServerError //Erro HTTP 500
        oResponse:Body = ErroInfo(errMensagem)
    SENÃO
        oResponse:Status = lrResponse::StatusOK
        oResponse:Body = "Sessão "+oSession:ID+" criada"
        oResponse:SetHeaderValue("SESSION_ID", oSession:ID)
    FIM
    
    oResponse:ContentType = lrResponse::ContentTXT
    RETORNA oResponse

Destroy() : (booleano, inteiro)

Destrói a sessão atual

Parâmetros: Nenhum

Retorno:

  • booleano: Sucesso da destruição
  • inteiro: código de erro

Exemplo:

Procedimento REST de destruição da sessão. O identificador da sessão é passado pelo solicitante em um cabeçalho SESSION_ID da requisição REST.

PROCEDIMENTO REST_DestroySession(pRequest é lrRequest) : lrResponse
    oSession é lrSession
    oResponse é lrResponse
    bOK é booleano
    eErro é inteiro
    
    oSession:ID = pRequest::GetHeaderValue("SESSION_ID")
    (bOK, eErro) = oSession:Destroy()
    
    SE NÃO bOK ENTÃO
        oResponse:Status = lrResponse::StatusUnauthorized //Status HTTP 401
        oResponse:Body = oSession:GetErrorMessage(eErro)
    SENÃO
        oResponse:Status = lrResponse::StatusOK
        oResponse:Body = "Sessão "+oSession:ID+" destruída"
    FIM
    
    oResponse:ContentType = lrResponse::ContentTXT
    RETORNA oResponse

GetData(Tag) : (Booleano, *)

Leitura de dados de sessão previamente salvos. O armazenamento de múltiplos dados é previsto, cada um identificado por uma etiqueta (ou Tag).

Parâmetro Tipo Descrição
Tag String Etiqueta do dado de sessão a recuperar

Retorno:

  • Booleano: Sucesso da leitura
  • *: Dado conforme escrito durante a chamada ao método SetData

Exemplo:

Leitura dos dados da sessão atual

PROCEDIMENTO REST_ReadSession(pRequest é lrRequest) : lrResponse
    oSession é lrSession
    oResponse é lrResponse
    bOK é booleano
    eErro é inteiro
    cData é cadeia
    
    oSession:ID = pRequest:GetHeaderValue("SESSION_ID")
    (bOK, cData) = oSession:GetData("IDADE_DO_CAPITAO")
    
    SE NÃO bOK ENTÃO
        oResponse:Status = lrResponse::StatusInternalServerError //Erro HTTP 500
        oResponse:Body = oSession:GetErrorMessage(eErro)
        oResponse:ContentType = lrResponse::ContentTXT
        RETORNA oResponse
    FIM
    
    oResponse:Body = "A idade do capitão é "+cData
    oResponse:ContentType = lrResponse::ContentTXT
    RETORNA oResponse

GetErrorMessage(Código de Erro) : String

Recuperação da mensagem de erro correspondente a um código ErrorSession*, no idioma atual. Permite retornar uma mensagem inteligível ao solicitante.

Parâmetro Tipo Descrição
Código de Erro Inteiro Código do erro cuja mensagem se deseja recuperar

Retorno: String. Mensagem do erro

Veja o exemplo do método Check() que utiliza GetErrorMessage()

Refresh() : (booleano, inteiro)

Atualiza o registro de data/hora do último acesso da sessão. Esta função deve ser chamada quando o usuário realiza uma ação suscetível de reinicializar o prazo de inatividade de sua sessão.

Nota: Os métodos GetData() e SetData() executam automaticamente um Refresh()

Parâmetros: Nenhum

Retorno:

  • Booleano: Sucesso ou não da inicialização
  • Inteiro: Número do erro

Exemplo:

Tratamento realizando uma atualização da sessão

PROCEDIMENTO REST_FazAlgumaCoisa(pRequest é lrRequest) : lrResponse
    oSession é lrSession
    oResponse é lrResponse
    bOK é booleano
    eErro é inteiro
    cData é cadeia
    
    oSession:ID = pRequest::GetHeaderValue("SESSION_ID")
    //Atualizamos a sessão para evitar que ela expire
    (bOK, eErro) = oSession:Refresh()
    
    SE NÃO bOK ENTÃO
        oResponse:Status = lrResponse::StatusUnauthorized //Status HTTP 401
        oResponse:Body = oSession:GetErrorMessage(eErro)
        oResponse:ContentType = lrResponse::ContentTXT
        RETORNA oResponse
    FIM
    
    ...
    ...
    tratamento
    ...
    ...
    
    oResponse:ContentType = lrResponse::ContentTXT
    RETORNA oResponse

SetCypheringKey(Chave)

Inicializa a chave de criptografia das sessões. Se nenhuma chave foi inicializada, os dados da sessão serão salvos em texto simples no formato JSON.

Atenção, não se deve alterar a chave de criptografia durante a execução, senão os dados de sessão já salvos se tornarão ilegíveis.

Parâmetro Tipo Descrição
Chave de criptografia Buffer Chave de criptografia dos dados de sessão. Na ausência de chave de criptografia, os dados de sessão serão escritos em texto simples no formato JSON

Retorno: Nenhum

SetData(Tag, Data) : (Booleano, Inteiro)

Escrita de dados de sessão. O armazenamento de múltiplos dados é previsto, cada um identificado por uma etiqueta (ou Tag).

Parâmetro Tipo Descrição
Tag String Etiqueta do dado de sessão a salvar
Data Qualquer tipo de dado armazenável em um variant Dado de sessão a memorizar

Retorno:

  • Booleano: Sucesso da leitura
  • Inteiro: Código de Erro

Exemplo:

Escrita dos dados da sessão atual

PROCEDIMENTO REST_WriteSession(pRequest é lrRequest) : lrResponse
    oSession é lrSession
    oResponse é lrResponse
    bOK é booleano
    eErro é inteiro
    cData é cadeia
    
    oSession:ID = pRequest::GetHeaderValue("SESSION_ID")
    cData = aleatorio(10,100)
    (bOK, cData) = oSession:SetData("IDADE_DO_CAPITAO", cData)
    
    SE NÃO bOK ENTÃO
        oResponse:Status = lrResponse::StatusInternalServerError //Erro HTTP 500
        oResponse:Body = oSession:GetErrorMessage(eErro)
        oResponse:ContentType = lrResponse::ContentTXT
        RETORNA oResponse
    FIM
    
    oResponse:Body = "Registramos na sessão a idade do capitão: "+cData
    oResponse:ContentType = lrResponse::ContentTXT
    RETORNA oResponse