Как да организирате ресурси в URL структурата на уеб приложението

Текущо състояние

Разработвам системно приложение за Управление на онлайн поръчки с PHP и трябва да проектирам REST съпоставяне на ресурси чрез URL схема.

Имам типични ресурси:

  • Клиент (има поръчки)
  • Поръчка (има билети)
  • Билет (има съобщения)
  • Съобщение

Мисля си за нещо подобно:

  1. Клиентски профил:

    example.com/customers/{customer-ID}
    
  2. Поръчки за {customer-ID}:

    example.com/customers/{customer-ID}/orders
    
  3. Билети за {order-ID}:

    example.com/customers/{customer-ID}/orders/{order-ID}/tickets
    
  4. Съобщения за {ticket-ID}

    example.com/customers/{customer-ID}/orders/{order-ID}/tickets/{ticket-ID}/messages
    

Констатации

Един ден гугъл и намерих тези квоти:

  1. #P9#
    example.com/{username}/followers
    
    #P10#
  2. #P11#
  3. #P12#
  4. #P13#
  5. #P14#
  6. #P15#
  7. #P16#

Въпроси

  • Правя ли нещата погрешно?
  • Трябва ли да избягвам пространството от имена клиенти, поръчки, билети и съобщения?
  • Има ли наистина сериозни опасения за сигурността?

Благодаря предварително!


person Pmpr    schedule 09.06.2016    source източник


Отговори (2)


Ако всички връзки, които описвате, са едно към много (не много към много), тогава не виждам какво печелите, като имате URL адреси, които например съдържат идентификатор на клиент, когато идентификаторът на поръчката е известен. Това е излишна информация и няма да предостави допълнителна полезна информация във вашите контролери.

Всъщност това може да причини ПО-ВЕЧЕ сложност от желаното, тъй като сега трябва да се справяте със случаи, в които може да има несъответствие на идентификатора на клиент за поръчка. Сега трябва да проверите всички тези условия и да върнете лош отговор на заявка, ако възникнат тези лоши условия. Защо да добавяте тези режийни разходи?

Може би само:

Клиентски профил:

example.com/customers/{customer-ID}

Поръчки за {customer-ID}:

example.com/customers/{customer-ID}/orders

Билети за {order-ID}:

example.com/orders/{order-ID}/tickets

Съобщения за {ticket-ID}

example.com/tickets/{ticket-ID}/messages

Ако обаче сте имали връзка много към много, това може да се промени. Да кажем например, че клиент може да въведе един билет, който покрива множество поръчки (което означава, че билетите вече са по-свързани с клиента, отколкото със самата поръчка), тогава може да имате нужда от URL адреси като следния в допълнение към показаните по-горе:

Вижте всички поръчки за даден билет:

example.com/tickets/{ticket-ID}/orders

Вижте всички билети за клиент:

example.com/customer/{customer-ID}/tickets
person Mike Brant    schedule 09.06.2016
comment
В предложената от вас схема каква е разликата между example.com/customers/{customer-ID}/orders и example.com/orders? - person Pmpr; 10.06.2016
comment
@Trix /orders вероятно ще изброи всички поръчки, докато /customers/{customer-ID}/orders ще изброи всички поръчки за този идентификатор на клиента. - person Mike Brant; 10.06.2016
comment
Тогава, когато клиент посети /orders, какво трябва да види той? Съобщение Достъпът е отказан!?! - person Pmpr; 10.06.2016
comment
@Trix Това зависи от вас да определите. Ако имате случай на използване за краен потребител (за разлика от потребител администратор) да види пълен списък с поръчки, тогава можете да върнете пълния списък. Ако нямате подходящ случай на употреба за потребител на edn там, вашето разрешение за този метод трябва да доведе до връщане на подходящ отговор от серия 4XX или 5XX. - person Mike Brant; 10.06.2016
comment
Tnx, но в спора с вашето предложение, какъв е проблемът с използването само на /orders & /orders/{order-ID} и въвеждането на нива на достъп в работа? Там можем да покажем на всеки потребител само неговото/неговото свързано съдържание - person Pmpr; 10.06.2016
comment
@Trix Бих предположил, че ще имате базова /orders/{order-ID} функционалност (въпреки че не го отбелязах по-горе). Както обикновено при RESTful услугите, винаги има начини да получите конкретен ресурс от даден тип. Мисля, че трябва да разберете всички модели на повиквания, използвани в тази услуга (както също отбеляза @MaksymStrukov) и кои модели на повиквания ще бъдат използвани от кой тип потребители, за да стигнете наистина до крайната стратегия. Вие вече сте предложили /customers/{customer-ID}/orders URL което ще ви даде всички поръчки за клиент. - person Mike Brant; 10.06.2016
comment
@Trix За да продължа коментара си... Обикновено в услугите RESTful не бихте използвали оторизация като механизъм за филтриране на набор от резултати. Използвате оторизация, за да позволите достъп до определени маршрути във вашето приложение. Поради тази причина не бих предложил да се прави нещо като използване на /orders в комбинация с данни за оторизация, за да се филтрира наборът от резултати от поръчки към тези, които са свързани само с крайния клиент. За това е предназначена релационната информация във вашата база данни. - person Mike Brant; 10.06.2016
comment
Благодаря, но не планирам да прилагам RESTful услуга. Това е уеб приложение и има потребителски интерфейс. - person Pmpr; 10.06.2016
comment
@Trix Service или не, изглежда, че основно се опитвате да подходите към това, като използвате RESTful URL стратегия за маршрутизиране. Ще ви е необходим някакъв механизъм за анализиране на предоставения URL адрес и за насочване на заявката към подходяща логика за изобразяване. Обикновено този вид механизъм разглежда и упълномощаването на ниво маршрут, за да реши дали да откаже заявката, преди дори да я прехвърли към логиката за изобразяване на страница. Мисля, че бихте искали да отделите този механизъм за оторизация от механизмите за филтриране на редове, които ще живеят в логиката ви за изобразяване на страницата. - person Mike Brant; 10.06.2016

Правя ли нещата погрешно?

Зависи. Изглежда, че сте на прав път, но е по-добре първо да решите каква функционалност трябва да предостави вашата услуга. В противен случай може да се окажете с безкраен брой url (ресурси) за внедряване. Например, ако трябва да изложите списък с поръчки за всички клиенти, ще искате да имате example.com/orders ресурс с параметри на низ на заявка, за да посочите критерии за търсене. В противен случай ще трябва първо да се направи запитване към всички клиенти и след това в цикъл да се изпращат заявки до example.com/customers/{customer-ID}/orders, за да се получат всички поръчки за всички клиенти. Така че първо помислете каква функционалност трябва да изложи вашата услуга и след това проектирайте ресурсите за нея.

Има ли наистина сериозни опасения за сигурността?

Няма нищо общо с дизайна на url (ресурси). Информацията за удостоверяване и упълномощаване обикновено влиза в http заглавките.

Също така, моля, помислете за добавяне на информация за версии към вашите URL адреси. Оказва се, че е супер полезно, когато трябва да поддържате няколко версии на вашите услуги

example.com/v1/customers/{customer-ID}/orders

or

v1.example.com/customers/{customer-ID}/orders

и т.н.

И накрая, ако ще поддържате множествено представяне за ресурс, например, можете да върнете списъка с клиенти като JSON, XML, HTML и т.н. добра практика е да го посочите и в URL адреса. Затова вземете своя формат за представяне по подразбиране и го изложете като example.com/customers и след това добавете информация за формата в края на URL адреса, ако поддържате други

example.com/customers.xml

or

example.com/customers.html

и т.н.

Дано помогне!

Мисля, че включването на идентификатори в URL може да не е добра практика

Е, има два основни подхода и двата имат своите минуси и плюсове. Първият използва имена или кратко описание на ресурса вместо ID. Например, вместо идентификатор на клиент можете да използвате неговото име, example.com/customers/amazon, където amazon е името на вашия клиент. Друг добър пример за подхода са новинарските сайтове, ако навигирате през cnn.com, ще видите всеки URL адрес на статия да съдържа заглавие на статия http://edition.cnn.com/2016/06/10/middleeast/israel-tel-aviv-shooting/index.html - „Заподозреният в Тел Авив е открит да се крие в дома на полицай извън службата“

Това е страхотно от гледна точка на SEO и URL адресите стават по-описателни и удобни за хората. Но ако трябва да промените името на клиента си, това трябва да промени URL адреса и има огромен риск от прекъсване на клиентите. Освен това има много неща, които трябва да имате предвид, докато прилагате подхода:

  • Трябва правилно да потвърдите имената на клиентите, така че да могат да бъдат добавени към URL адрес
  • Трябва или да забраните промяната на името на клиента, или да я обработите правилно, като върнете 301 („Преместено за постоянно“) и посочите новия URL адрес в заглавката на местоположението, така че клиентът да е наясно с новия URL адрес
  • и т.н.

Основното предимство на подхода за идентификатори е, че URL адресите винаги са статични и не е нужно да се притеснявате за нещата по внедряването по-горе.

И двата подхода са валидни от гледна точка на REST, така че зависи от вас да решите

person Maksym Strukov    schedule 09.06.2016
comment
Така че първо помислете каква функционалност трябва да разкрие вашата услуга и след това проектирайте ресурсите за нея. : Клиентите имат поръчки, които от своя страна може да имат билети, като всеки билет има множество съобщения. функционалността е очевидна, тъй като клиентът трябва да може да изпраща поръчки. изпращат билети по техните поръчки и добавят съобщения към своите билети - person Pmpr; 10.06.2016
comment
@Trix Да, но може да имате администратори, които може да се наложи да заявяват поръчки за всички клиенти, както е описано в отговора ми, може да има други случаи, както описа Майк. Това е само съвет, за да не пропуснете нищо. Ако това, което посочихте по-горе, е всичко, което услугата ви трябва да изложи, тогава сте на прав път, както казах в отговора си - person Maksym Strukov; 10.06.2016
comment
Благодаря, но е очевидно, че всяко приложение се нуждае от някои администраторски неща. Искам да знам дали излагането на ресурс като такъв е добра практика или не, подкрепено с убедителни доказателства - person Pmpr; 10.06.2016
comment
@Trix Какво точно имате предвид, като излагате ресурс като такъв? Имате предвид моя пример с получаване на поръчка с и без идентификатор на клиента в URL адреса? - person Maksym Strukov; 10.06.2016
comment
Няма реална разлика между ID и Title. и двете трябва да бъдат проверени на ниво маршрутизиране. Също така публикациите в блогове и новините са публични ресурси, докато поръчките на клиенти не са. Мисля, че имате недоразумения относно моя въпрос. - person Pmpr; 10.06.2016
comment
@Trix Не мисля, че проблемът е ID. И така, какво ще стане, ако неоторизиран използван се опита да получи достъп до потребителски профил на /customer/{id}? Ако имате подходящо удостоверяване и оторизация, можете да накарате услугата да формира подходящ 4XX или 5XX HTML код за отговор и да откажете достъп до този ресурс. Ако се притеснявате, че потребителят ще познае основен идентификационен номер на цяло число, тогава можете също да обмислите използването на поле тип GUID, където имате уникален (обикновено буквено-цифров) низ, който се генерира за всеки клиент. Това прави отгатването на GUID много по-трудно. - person Mike Brant; 10.06.2016
comment
@MikeBrant Това е смисълът и искам да знам какво стои зад констатации №2 във въпроса ми. - person Pmpr; 10.06.2016