Tanto quanto posso dizer, cada recurso individual deve ter apenas um caminho canônico . Portanto, no exemplo a seguir, quais seriam os bons padrões de URL?
Tomemos como exemplo uma representação restante das empresas. Neste exemplo hipotético, cada empresa possui 0 ou mais departamentos e cada departamento possui 0 ou mais funcionários.
Um departamento não pode existir sem uma empresa associada.
Um funcionário não pode existir sem um departamento associado.
Agora eu consideraria a representação natural dos padrões de recursos.
/companies
Uma coleção de empresas - aceita colocar para uma nova empresa. Obter para toda a coleção./companies/{companyId}
Uma empresa individual. Aceita GET, PUT e DELETE/companies/{companyId}/departments
Aceita POST para um novo item. (Cria um departamento dentro da empresa.)/companies/{companyId}/departments/{departmentId}/
/companies/{companyId}/departments/{departmentId}/employees
/companies/{companyId}/departments/{departmentId}/employees/{empId}
Dadas as restrições, em cada uma das seções, sinto que isso faz sentido se um pouco profundamente aninhado.
No entanto, minha dificuldade surge se eu quiser listar ( GET
) todos os funcionários em todas as empresas.
O padrão de recursos para o qual seria mais próximo /employees
(A coleção de todos os funcionários)
Isso significa que eu deveria ter /employees/{empId}
também porque, nesse caso, existem dois URIs para obter o mesmo recurso?
Ou talvez o esquema inteiro deva ser achatado, mas isso significa que os funcionários são um objeto de nível superior aninhado.
Em um nível básico, /employees/?company={companyId}&department={deptId}
retorna exatamente a mesma visão dos funcionários que o padrão mais profundamente aninhado.
Qual é a melhor prática para padrões de URL em que os recursos pertencem a outros recursos, mas devem ser consultados separadamente?
fonte
Respostas:
O que você fez está correto. Em geral, pode haver muitos URIs para o mesmo recurso - não há regras que digam que você não deve fazer isso.
E geralmente, você pode precisar acessar itens diretamente ou como um subconjunto de outra coisa - para que sua estrutura faça sentido para mim.
Só porque os funcionários estão acessíveis no departamento:
company/{companyid}/department/{departmentid}/employees
Não significa que eles também não possam ser acessíveis na empresa:
company/{companyid}/employees
O que retornaria funcionários para essa empresa. Depende do que é necessário para o seu cliente consumidor - é para isso que você deve projetar.
Mas espero que todos os manipuladores de URLs usem o mesmo código de suporte para atender às solicitações, para que você não esteja duplicando o código.
fonte
/company/3/department/2/employees/1
). Se a API fornecer maneiras de obter cada recurso, a realização de cada uma dessas solicitações poderá ser feita em uma biblioteca do lado do cliente ou como um terminal único que reutilize o código./company/*
deve retornar apenas o recurso da empresa e não alterar o tipo de recurso. Nada disso é especificado pelo REST - geralmente é mal especificado - apenas preferência pessoal.Eu tentei as duas estratégias de design - pontos de extremidade aninhados e não aninhados. Eu descobri que:
se o recurso aninhado tiver uma chave primária e você não tiver sua chave primária pai, a estrutura aninhada exigirá que você a obtenha, mesmo que o sistema não a exija.
pontos de extremidade aninhados geralmente requerem pontos de extremidade redundantes. Em outras palavras, você precisará mais frequentemente do ponto de extremidade / funcionários para poder obter uma lista de funcionários entre os departamentos. Se você possui / funcionários, o que exatamente / empresas / departamentos / funcionários compram para você?
pontos finais de aninhamento não evoluem tão bem. Por exemplo, talvez você não precise procurar funcionários agora, mas pode precisar mais tarde e, se tiver uma estrutura aninhada, não terá outra opção a não ser adicionar outro ponto de extremidade. Com um design não aninhado, você apenas adiciona mais parâmetros, o que é mais simples.
Às vezes, um recurso pode ter vários tipos de pais. Resultando em vários pontos de extremidade, todos retornando o mesmo recurso.
pontos finais redundantes tornam os documentos mais difíceis de escrever e também tornam a API mais difícil de aprender.
Em resumo, o design não aninhado parece permitir um esquema de terminal mais flexível e mais simples.
fonte
Mudei o que fiz da pergunta para uma resposta em que mais pessoas provavelmente o verão.
O que fiz foi ter os pontos de extremidade de criação no ponto de extremidade aninhado. O ponto de extremidade canônico para modificar ou consultar um item não está no recurso aninhado .
Portanto, neste exemplo (apenas listando os pontos de extremidade que alteram um recurso)
POST
/companies/
cria uma nova empresa retorna um link para a empresa criada.POST
/companies/{companyId}/departments
quando um departamento é criado, o novo departamento retorna um link para/departments/{departmentId}
PUT
/departments/{departmentId}
modifica um departamentoPOST
/departments/{deparmentId}/employees
cria um novo funcionário retorna um link para/employees/{employeeId}
Portanto, existem recursos no nível raiz para cada uma das coleções. No entanto, a criação está no objeto proprietário .
fonte
POST
significadoPUT
, e caso contrário.Eu li todas as respostas acima, mas parece que elas não têm uma estratégia comum. Encontrei um bom artigo sobre as práticas recomendadas na Design API da Microsoft Documents . Eu acho que você deveria se referir.
.
fonte
A aparência dos seus URLs não tem nada a ver com o REST. Qualquer coisa serve. Na verdade, é um "detalhe de implementação". Assim como você nomeia suas variáveis. Tudo o que precisam ser únicos e duráveis.
Não perca muito tempo com isso, basta fazer uma escolha e cumpri-lo / ser consistente. Por exemplo, se você segue hierarquias, o faz para todos os seus recursos. Se você usar parâmetros de consulta ... etc, assim como as convenções de nomenclatura no seu código.
Por quê então ? Tanto quanto eu sei que uma API "RESTful" deve ser navegável (você sabe ... "Hipermídia como o mecanismo do estado do aplicativo"), portanto, um cliente de API não se importa com o que são seus URLs, desde que sejam válido (não há SEO, nenhum ser humano que precise ler esses "URLs amigáveis", exceto para depuração ...)
O quão agradável / compreensível é um URL em uma API REST é interessante apenas para você como desenvolvedor da API, não como cliente da API, como seria o nome de uma variável em seu código.
O mais importante é que seu cliente de API saiba como interpretar seu tipo de mídia. Por exemplo, ele sabe que:
Abaixo está um exemplo de troca HTTP (os corpos estão no yaml, pois é mais fácil escrever):
Solicitação
Resposta: uma lista de links para o recurso principal (empresas, pessoas, o que for ...)
Pedido: link para empresas (usando body.links.companies da resposta anterior)
Resposta: uma lista parcial de empresas (nos itens), o recurso contém links relacionados, como o link para obter as próximas empresas (body.links.next) e outro (modelo) para a pesquisa (body.links.search)
Então, como você vê se segue o caminho dos links / relações, como você estrutura a parte do caminho dos seus URLs não tem valor para o seu cliente de API. E se você está comunicando a estrutura de seus URLs ao cliente como documentação, não está fazendo REST (ou pelo menos não está no nível 3, conforme " Modelo de maturidade de Richardson ")
fonte
Eu discordo deste tipo de caminho
Se você deseja obter departamentos, acho melhor usar um recurso / departamentos
Suponho que você tenha uma
companies
tabela e umadepartments
tabela e depois classes para mapeá-las na linguagem de programação usada. Também presumo que os departamentos possam ser anexados a outras entidades que não as empresas; portanto, um recurso / departamentos é direto, é conveniente ter recursos mapeados para tabelas e você também não precisa de muitos pontos de extremidade, pois pode reutilizarpara qualquer tipo de pesquisa, por exemplo
Se você deseja criar um departamento, o
o recurso deve ser usado e o corpo da solicitação deve conter o ID da empresa (se o departamento puder ser vinculado a apenas uma empresa).
fonte
GET /companies/{companyId}?include=departments
, uma vez que isso permite que a empresa e seus departamentos sejam buscados em uma única solicitação HTTP. O Fractal faz isso muito bem./departments
nó de extremidade para ser acessível apenas por um administrador, e cada empresa acessa seus próprios departamentos apenas através de `/ companies / {companyId} / departamentos`O Rails fornece uma solução para isso: aninhamento superficial .
Eu acho que isso é bom porque, quando você lida diretamente com um recurso conhecido, não há necessidade de usar rotas aninhadas, conforme discutido em outras respostas aqui.
fonte