http servers

Описание: Наиболее перспективное направление развития компьютерных наук. Надо быть в теме!

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 5 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#7 dyvniy » Сб, 20 июня 2015, 10:08:31

timing in chrome
Изображение
Evolution network performance
https://developer.chrome.com/devtools/docs/network#resource-network-timing
Спойлер
The Network panel records information about each network operation in your application, including detailed timing data, HTTP request and response headers, cookies, WebSocket data, and more. The Network panel helps you answer questions about the network performance of your web application, such as:

Which resource had the slowest time to first byte?
Which resources took the longest time to load (duration)?
Who initiated a particular network request?
How much time was spent in the various network phases for a particular resource?
About the Resource Timing API
The Network panel uses the Resource Timing API, a JavaScript API that provides detailed network timing data for each loaded resource. For example, the API can tell you precisely when the HTTP request for an image started, and when the image's final byte was received. The following illustration shows the network timing data points that the Resource Timing API provides.

Resource timing overview

The API is available to any web page, not just DevTools. In Chrome, it's exposed as methods on the global window.performance object. The performance.getEntries() method returns an array of "resource timing objects", one for each requested resource on the page.

Try this: open the JavaScript console on the current page, enter the following at the prompt, and hit Return:

window.performance.getEntries()[0]
This evaluates the first element in the array of resource timing objects and displays its properties in the console, as shown below.

Performance resource timing

Each timestamp is in microseconds, following the High ResolutionTime specification. This API is available inChrome as the window.performance.now() method.

Network panel overview
The Network panel automatically records all network activity while DevTools is open. The first time you open the panel it may be empty. Reload the page to start recording, or simply wait for network activity to occur in your application.

Network overview

Each requested resource is added as a row to the Network table, which contains the columns listed below. Note the following about the Network table:

Not all columns listed below are visible by default; you can easily show or hide columns.
Some columns contain a primary field and a secondary field (Time and Latency, for example). When viewing the Network table with large resource rows both fields are shown; when using small resource rows only the primary field is shown.
You can sort the table by a column's value by clicking the column header. The the Timeline column behaves a bit differently: clicking its column header displays a menu of additional sort fields. See Waterfall view and Sorting and filtering for more information.
Name and Path
The name and URL path of the resource, respectively.
Method
The HTTP method used for the request. For example: GET or POST.
Status and Text
The HTTP status code and text message.
Domain
The domain of the resource request.
Type
The MIME type of the requested resource.
Initiator
The object or process that initiated the request. It can have one of the following values:
Parser
Chrome's HTML parser initiated the request.
Redirect
A HTTP redirect initiated the request.
Script
A script initiated the request.
Other
Some other process or action initiated the request, such as the user navigating to a page via a link, or by entering a URL in the address bar.
Cookies
The number of cookies transferred in the request. These correspond to the cookies shown in the Cookies tab when viewing details for a given resource.
Set-Cookies
The number of cookies set in the HTTP request.
Size and Content
Size is the combined size of the response headers (usually a few hundred bytes) plus the response body, as delivered by the server. Content is the size of the resource's decoded content. If the resource was loaded from the browser's cache rather than over the network, this field will contain the text (from cache).
Time and Latency
Time is total duration, from the start of the request to the receipt of the final byte in the response. Latency is the time to load the first byte in the response.
Timeline
The Timeline column displays a visual waterfall of all network requests. Clicking the header of this column reveals a menu of additional sorting fields.
Preserving the network log upon navigation
By default, the current network record log is discarded when you navigate to another page, or reload the current page. To preserve the recording log in these scenarios, click the black Preserve log upon navigation button Don't preserve log on navigation at the bottom of the Network panel; new records are appended to the bottom of the table. Click the same button again (now red Preserve resources on navigation) to disable log preservation.

Sorting and filtering
By default, resources in the Network table are sorted by the start time of each request (the network "waterfall"). You can sort the table by another column value by clicking the column header. Click the header again to change the sort order (ascending or descending).

Sort by

The Timeline column is unique from the others in that, when clicked, it displays a menu of additional sort fields.

Timeline column

The menu contains the following sorting options:

Timeline — Sorts by the start time of each network request. This is the default sort, and is the same as sorting by the Start Time option).
Start Time — Sorts by the start time of each network request (same as sorting by the Timeline option).
Response Time — Sorts by each request's response time.
End Time — Sorts by the time when each request completed.
Duration — Sorts by the total time of each request.
Latency — Sorts by the time between the start of the request and the beginning of the response (also known as the "time to first byte").
To filter the Network table to only show certain types of resources, click one of the content types along the bottom of the panel: Documents, Stylesheets, Images, Scripts, XHR, Fonts, WebSockets, and Other. In the following screenshot only CSS resources are shown. To view all content types, click the All filter button.

Filter type

Advanced filtering
In addition to resource type filtering, you can narrow down resources by filter queries. For example, to find all resources which have a status code of 200, you can enter the query StatusCode:200 in the filter input field.

Advanced filtering in the Network Panel

Take note of the following behaviour: A filter query includes a type (StatusCode) and value (200). A filter query is case insensitive, so you can type uppercase or lowercase. The filter type gives you autocomplete suggestions. Use the arrows keys to form a selection and press Tab to select it. The filter value has autocomplete which shows you values present in the current network recording. Quickly preview the results of your query, use the Up / Down arrow keys to cycle through the autocomplete suggestions. The results appear immediately even you do not press enter or tab to complete the selection. To negate a filter query, prepend the query with a dash (-), for example -StatusCode:200.

Available filter types:

domain
The domain portion from the URL of the resource. E.g. www.google-analytics.com.
has-response-header
Checks the resource has a response header, regardless of the value. E.g. Access-Control-Allow-Origin.
is
Shows requests running at the current point in time. Current available value: running
larger-than
Shows requests with a transfer size larger than the specified amount. Units assumed in bytes, but kilobyte (k) & megabyte (m) units also allowed: E.g. larger-than:50, larger-than:150k, larger-than:2m
method
The HTTP method used. E.g. GET.
mime-type
Also known as Content-type - the identifier for the type of resource. E.g. text/html.
scheme
The scheme portion in a URL. E.g. https.
set-cookie-name
The name of the cookie as set by the server. E.g. loggedIn (assuming a cookie like loggedIn=true).
set-cookie-value
The value of the cookie set by the server. E.g. true (assuming a cookie like loggedIn=true).
set-cookie-domain
The domain of the cookie as set by the server. E.g. foo.com (assuming a cookie like loggedIn=true; Domain=foo.com; Path=/; Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly).
status-code
The status code in the HTTP response. E.g. 200.
To use a query shown in the above list, construct it in the format of: <Filter Type>:<Description>. You will almost always want to use the autocomplete suggestions which ensures your query is valid.

Adding and removing table columns
You can change the default set of columns displayed by the Network table. To show or hide a column, Right+click or Control+click (Mac only) in the table header and select or deselect column names from the list.

Add or remove columns

Changing resource row sizes
You can view the Network table with large resource rows (the default), or small resource rows. Click the blue Use small resource rows toggle button Small resource rows at the bottom of the panel to view small rows. Click the same button (now gray Large resource rows) to view large resource rows again. Large rows enable some columns to display two text fields: a primary field and a secondary field (Time and Latency, for instance). When viewing small rows only the primary field is displayed.

Resized resource rows
The network table with small resource rows and just the timeline column.
Waterfall view
The waterfall view in the network panel graphs the time it took to load each resource.From the start of the HTTP request to the receipt of the final byte of the response.

Each resource loading time is represented as a bar.This has color-coded information related to each resource.Each color specifies a different step needed to recieve the resource.The larger the bar grows represents more data being trasmitted for the request.

Network timeline view
The network timeline for a simple web page.
Hovering your mouse over the bar itself will present the complete timing data.This is the same information that's presented in the Timing details tab for a given resource.

Timeline view on hover
Network timing details revealed on hover.
The waterfall highlights DOMContentLoaded and load events display with blue and red vertical lines. When the engine has completed parsing of the main document the DOMContentLoaded event fires. Upon retrieving all the page's resources the load event will fire.

DOM event lines
The event lines as displayed over the timeline.
You may enable in the network settings to view the timeline as color-coded by resource type.If you do the network timing information is still accessible through the tooltip.Waterfall bars are color-coded as follows:

Documents
Stylesheets
Images
Scripts
XHR
Fonts
Other
Saving and copying network information
Right-clicking or Ctrl + Click (Mac only) within the Network table a context menu appears with several actions. Some of these actions apply to the resource row under the mouse click (like copying HTTP request headers), while others apply to the entire network recording (such as saving a Network recording as a HAR file).

Right-click on Network

The following menu actions apply to the selected resource:

Open Link in New Tab — Opens the resource in a new tab. You can also double-click the resource name in the Network table.
Copy Link Address — Copies the resource URL to the system clipboard.
Copy Request Headers — Copies the HTTP request headers to the system clipboard.
Copy Response Headers — Copies the HTTP response headers to the system clipboard.
Copy as cURL — Copies the network request as a cURL command string to the system clipboard. See Copying requests as cURL commands.
Replay XHR — If the associated request is an XMLHTTPRequest, re-sends the original XHR.
Copying requests as cURL commands
cURL is a command line tool for making HTTP transactions. The Network panel's Copy as cURL command recreates an HTTP request (including HTTP headers, SSL certificates, and query string parameters) and copies it as a cURL command string to the clipboard. You can then paste the string into a terminal window (on a system with cURL) to execute the same request.

Below is an example cURL command line string taken from a XHR request on the Google News home page.

curl 'http://news.google.com/news/xhrd=us' -H 'Accept-Encoding: gzip,deflate,:sdch' -H 'Host: news.google.com' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1510.0 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://news.google.com/nwshp?hl=en&tab=wn' -H 'Cookie: NID=67=eruHSUtoIQA-HldQn7U7G5meGuvZOcY32ixQktdgU1qSz7StUDIjC_Knit2xEcWRa-e8CuvmADminmn6h2_IRpk9rWgWMdRj4np3-DM_ssgfeshItriiKsiEXJVfra4n; PREF=ID=a38f960566524d92:U=af866b8c07132db6:FF=0:TM=1369068317:LM=1369068321:S=vVkfXySFmOcAom1K' -H 'Connection: keep-alive' --compressed
Saving network data
You can save the data from a network recording as a HAR (HTTP Archive) file, or copy the records as a HAR data structure to your clipboard. A HAR file contains a JSON data structure that describes the network "waterfall". Several third-party tools can reconstruct the network waterfall from the data in the HAR file.

To save a recording:

Right+click or Control+click on the Network table.
In the context menu that appears, choose one of the following actions:
Copy All as HAR — Copies the network recording to the system clipboard in the HAR format.
Save as HAR with Content — Saves all network data to a HAR file along with each page resource. Binary resources, including images, are encoded as Base64-encoded text.
For more information, Web Performance Power Tool: HTTP Archive (HAR).

Network resource details
When you click a resource name in the Network table a tabbed window appears that contains the following additional details:

HTTP request and response headers
Resource preview
HTTP response
Cookie names and values
WebSocket messages
Resource network timing
HTTP headers
The Headers tab displays the resource's request URL, HTTP method, and response status code. Additionally, it lists the HTTP response and request headers and their values, and any query string parameters. You can view HTTP headers parsed and formatted, or in their source form by clicking the View parsed/View source toggle button, respectively, located next to each header's section. You can also view parameter values in their decoded or URL encoded forms by clicking the View decoded/View URL encoded toggle button next to each query string section.

Network headers

You can also copy request and response headers to your clipboard.

Resource previews
The Preview tab displays a preview of the resource, when available. Previews are currently displayed for image and JSON resources, as shown below.

Resource JSON preview

Resource image preview

You can view the resource's unformatted response on the Responsetab.

HTTP response
The Response tab contains the resource's unformatted content. Below is a screenshot of a JSON data structure that was returned as the response for a request.

Resource response preview

You can also view formatted previews of some resource types, including JSON data structures and images.

Cookies
The Cookies tab displays a table of all the cookies transmitted in theresource's HTTP request and response headers. You can also clear all cookies.

Resource cookies

The Cookies table contain the following columns:

Name
The cookie's name.
Value
The value of the cookie.
Domain
The domain the cookie belongs to.
Path
The URL path the cookie came from.
Expires / Max-Age
The value of the cookie's expires or max-age properties.
Size
The size of the cookie in bytes.
HTTP
This indicates that the cookie should only be set by the browser in the HTTP request, and cannot be accessed with JavaScript.
Secure
The presence of this attribute indicates that the cookie should only be transmitted over a secure connection.
WebSocket frames
The Frames tab shows messages sent or received over a WebSocket connection. This tab is only visible when the selected resource initiated a WebSocket connection. The table contains the following columns:

Data
The message payload. If the message is plain text, it's displayed here. For binary opcodes, this field displays the opcode's name and code. The following opcodes are supported:
Continuation Frame
Binary Frame
Connection Close Frame
Ping Frame
Pong Frame
Length
The length of the message payload in bytes.
Time
The time stamp when the message was created.
Messages are color-coded according to their type. Outgoing text messages are color-coded light-green; incoming text messages are white:

Websocket text

WebSocket opcodes are light-yellow:

Websocket opcodes

Errors are light-red.

Notes about current implementation:

To refresh the Frames table after new messages arrive, click the resource name on the left.
Only the last 100 WebSocket messages are preserved by the Frames table.
Resource network timing
The Timing tab graphs the time spent on the various network phases involved loading the resource. This is the same data displayed when you hover over a resource bar in the waterfall view.

Resource network timing graph

Stalled/Blocking
Time the request spent waiting before it could be sent. This time is inclusive of any time spent in proxy negotiation. Additionally, this time will include when the browser is waiting for an already established connection to become available for re-use, obeying Chrome's maximum six TCP connection per origin rule.
Proxy Negotiation
Time spent negotiating with a proxy server connection.
DNS Lookup
Time spent performing the DNS lookup. Every new domain on a page requires a full roundtrip to do the DNS lookup.
Initial Connection / Connecting
Time it took to establish a connection, including TCP handshakes/retries and negotiating a SSL.
SSL
Time spent completing a SSL handshake.
Request Sent / Sending
Time spent issuing the network request. Typically a fraction of a millisecond.
Waiting (TTFB)
Time spent waiting for the initial response, also known as the Time To First Byte. This time captures the latency of a round trip to the server in addition to the time spent waiting for the server to deliver the response.
Content Download / Downloading
Time spent receiving the response data.
Additional resources
To learn more optimizing the network performance of your application, see the following resources:

Use PageSpeed Insights to identify performance best practices that can be applied to your site, and PageSpeed optimization tools to automate the process of applying those best practices.
High Performance Networking in Google Chrome discusses Chrome network internals and how you can take advantage of them to make your site faster.
How gzip compression works provides a high level overview gzip compression and why it's a good idea.
Web Performance Best Practices provides additional tips for optimizing the network performance of your web page or application.
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 5 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#8 dyvniy » Вт, 1 сентября 2015, 11:45:37

Как не надо работать с http
http://habrahabr.ru/company/yandex/blog/265569/
Спойлер
15 тривиальных фактов о правильной работе с протоколом HTTP
Разработка систем передачи данных*, Разработка*, Веб-разработка*, API*, Блог компании Яндекс
Внимание! Реклама! Пост оплачен Капитаном Очевидность!

Ниже под катом вы найдёте 15 пунктов, описывающих правильную организацию ресурсов, доступных по протоколу HTTP — веб-сайтов, «ручек» бэкенда, API и прочая. «Правильный» здесь означает «соответствующий рекомендациям и спецификациям». Большая часть ниженаписанного почти дословно переведена из официальных стандартов, рекомендаций и best practices от IETF и W3C.



Вы не найдёте здесь абсолютно ничего неочевидного. Нет, серьёзно, каждый веб-разработчик теоретически эти 15 пунктов должен освоить где-то в районе junior developer-а и/или второго-третьего курса университета.

Однако на практике оказывается, что великое множество веб-разработчиков эти азы таки не усвоило. Читаешь документацию к иным API и рыдаешь. Уверен, что каждый читатель таки найдёт в этом списке что-то новое для себя.

1. URL идентифицирует ресурс — некоторую разделяемую сущность. Файл — ресурс. Ручка, которая что-то ищет — ресурс. Вызов метода — не ресурс. Если вы хотите шарахнуть из пушки по Луне, то вот так делать не надо:
GET /?method=шарахнуть&to=Луна

Заведите ресурс «шарахалка», и тогда у вас всё будет логично:
POST /шарахалка/?to=Луна


Почему POST, а не GET? Читай ниже.

2. URL состоит из схемы (протокола), хоста, пути (path), запроса (query) и фрагмента. Путь используется для организации иерархических ресурсов, запрос — для неиерархических ресурсов и для параметров операции. Фрагмент идентифицирует подчинённый ресурс, не имеющий прямого URL.

Scheme Host Path Query Fragment
↓ ↓ ↓ ↓ ↓
http://nyashnye-kotiki.xxx/breeds/maine-coon/?deliver_to=Moscow#photo

Если на вашем сайте «Няшные котики» есть каталог по породам, то его вполне логично организовать в виде частей path, поскольку каждый котик принадлежит ровно к одной породе. А вот доставлять одного котика можно в несколько городов, поэтому фильтр «с доставкой в город N» следует организовать через query.

3. Обращение по HTTP состоит из применения метода (глагола) к URL. Результатом такого применения должно быть — сюрприз-сюрприз! — то, что в глаголе написано. То есть GET возвращает представление ресурса, DELETE удаляет и т.п.

4. Методы GET, HEAD, OPTIONS — безопасные. Предполагается, что вызов этих методов состояния ресурса не изменяет. Поэтому многие сетевые агенты — такие, например, как префетчер ссылок в браузере или мессенджере — считают себя вправе по таким ссылкам ходить без явного волеизъявления пользователя. ИЧСХ, никаких стандартов не нарушают.

5. По умолчанию методы GET и HEAD кэшируются, OPTIONS, POST, PUT, PATCH, DELETE — нет. Поэтому если вы шарахнули по Луне методом POST, вы можете быть (почти) уверены, что этот запрос выполнится. Если вы шарахаете методом GET, какой-нибудь промежуточный прокси может ВНЕЗАПНО отдать вам ответ из кэша, и шарах в реальности не произойдёт.



6. Операции GET, PUT, DELETE симметричны. PUT кладёт нечто по URL-у (создавая новый ресурс или перезаписывая старый), GET по этому URL-у возвращает представление того, что положил PUT, DELETE удаляет ресурс.
Метод HEAD синонимичен по семантике методу GET, но не возвращает тело ответа, а только его заголовки (метаинформацию о ресурсе).

7. POST используется в том случае, если у вас нет URL, к которому вы хотите применить операцию. Например, если пользователь пишет новое сообщение в тредик на форуме, он может сам вычислить его id и сделать:
PUT /threads/php-rulezz/messages/100500

Если клиенту генерировать id не разрешено, ему придётся делать POST на ресурс уровнем выше по иерархии:
POST /threads/php-rulezz/messages

И этот ресурс сам создаст новое сообщение.
Обратите внимание, если вы по ошибке или вследствие сетевых проблем повторите POST запрос — создастся второе сообщение в треде, идентичное первому. PUT вы можете делать хоть 100500 раз, результат не изменится. Это свойство называется идемпотентностью.
Ладно создание постов на форуме. Вот если вы делаете тяжёлую и дорогую операцию по пользовательскому запросу — очень рекомендуется выполнять для этого идемпотентный запрос. А то может получиться как на картинке:

Разумеется, использование идемпотентного PUT порождает свои проблемы — в частности, как разрешать конфликты. Придётся больше программировать, зато результат будет более надёжным и безопасным.

8. PUT может использоваться как для создания новых ресурсов, так и для обновления старых. Однако в случае использования PUT для перезаписи предполагается, что в теле запроса передаётся закодированный ресурс целиком. Если же вы хотите модифицировать ресурс, т.е. изменить его внутреннее представление без полной перезаписи, то для этого был придуман метод PATCH. Этот метод некэшируемый, небезопасный и неидемпотентный.

9. Коды ответа нужны в первую очередь для того, чтобы клиент мог понять, что ему делать дальше. 3хх говорит, что для успешного выполнения запроса нужно выполнить дополнительное действие. 4хх говорит, что клиент, составляя запрос, сделал что-то неправильно и, обычно, о том, что умолять бесполезно — повторное выполнение запроса всё равно выкинет ошибку. В 4хх крайне рекомендуется включать информацию о том, что конкретно клиент сделал не так. 5хх говорит о том, что клиент всё сделал правильно — проблема на стороне сервера.

Обычно при успешном выполнении операции сервер отвечает на GET — 200, на PUT — 201 Created (если ресурс создан) или 200 (ресурс обновлён), на DELETE — 204 (операция успешна, возвращать нечего), на POST — 200 или 201 (во втором случае в заголовке, обычно Location, указывается URL созданного ресурса).

10. Работая с HTTP-статусами, не наступите на популярные грабли:
статус 401 Unauthorized обязан сопровождаться заголовком WWW-Authenticate и, таким образом, применим только тогда, когда клиент аутентифицируется посредством HTTP-аутентификации; во всех остальных случаях следует использовать 403 Forbidden;
статусы 3xx — это не только редиректы; они показывают, что клиент должен выполнить дополнительное действие, иначе запрос не может считаться успешным; например, по статусу 304 Not Modified клиент должен взять актуальную версию ресурса из кэша;
статус 404, как ни странно, один из немногих 4xx статусов, которые клиент имеет право повторять — он означает, что ресурса сейчас нет, но вполне возможно, что он появится; вообще 404 — статус неопределённости, который используется, если сервер не хочет раскрывать механику ошибки; для того, чтобы индицировать клиенту, что без дополнительных действий с его стороны ресурс не появится, следует использовать 410 Gone (ресурс был удалён) либо общий статус 400.



11. Существует особый подкласс URL-ов, которые кодируют в себе и ресурс, и действие над ним. В англоязычной литературе их принято называть Capability URLs. Классический пример такого URL — ссылки на восстановление паролей, а также всевозможные «секретные» прямые ссылки на всяческие ресурсы.

12. Поскольку основная опасность при работе с Capability URL — возможность их утечки, следует максимально закрыть возможности случайно такой URL найти или перехватить:
для генерации секретных частей URL должен использоваться сильный генератор случайных строк (например, UUID), исключающий возможности найти Capability URL перебором; разумеется, URL не должен генерироваться детерминированным способом типа md5(username) и такие URL нельзя пропускать через сокращатели ссылок;
Capability URLs должны работать только по HTTPS;
страницы, доступные через Capability URL, должны быть закрыты wildcard-ом от индексации роботами.


13. Должны быть предусмотрены меры минимизации возможного ущерба:
пользователь, создавший Capability URL (например, расшаривший документ), должен иметь возможность сделать обратную операцию, т.е. отозвать URL;
Capability URLs должны протухать со временем; чем опаснее предоставляемый доступ, тем короче должен быть срок жизни URL.


14. Наконец, сами «секретные» страницы должны быть защищены от сливания данных сторонним агентам:
на них не должно быть никаких third-party скриптов и картинок, желательно — на уровне CSP;
на них не должно быть ссылок на third-party сайты; если они необходимы, то нужно скрывать referrer, например, через rel=«noreferrer»;
вообще желательно через Referrer Policy настроить скрытие referrer-а;
желательно сразу после захода пользователя через History API менять URL в адресной строке браузера, чтобы его нельзя было подсмотреть через плечо;
если ссылка предполагает какое-то действие (например, смену пароля), то на секретной странице должна быть форма (кнопка, скрипт), которую требуется отослать, чтобы действие осуществить, причём эта форма должно быть подписана CSRF-токеном (иначе префетчер браузера / почтового клиента / мессенджера сможет восстановить пароль за юзера).


15. Всё описанное выше существует в стандартах исключительно в форме рекомендации, и принудить кого-либо к строгому исполнению этих рекомендаций нельзя. Я уже не первый раз рассказываю про всю эту тривию, и часто слышу в ответ «да плевать я на всё это хотел, придумали какой-то ненужной ерунды; как у меня работали все сервисы только на GET, так и дальше будут, мучайтесь со своими PUT-ами и DELETE-ми сами».

Разумеется, вы вольны писать свой сервис сами. Но имейте, пожалуйста, в виду, что между вашим сервером и вашим клиентом, даже если они стоят физически рядышком в одном ДЦ, есть огромное множество других сетевых агентов — браузеров, прокси, роутеров, имплементаций HTTP-протокола в разных языках программирования и разных ОС, DPI-оборудование провайдеров и так далее. Все эти агенты плюс-минус имплементируют протокол HTTP с оглядкой на RFC.

Если вдруг клиентский браузер запрефетчит GET-ссылку и шарахнет по Луне — это будет ваша вина, бесполезно писать производителю. Если у вас деньги переводятся GET-запросом, а имплементация HTTP протокола в вашем языке программирования, не дождавшись ответа от соседнего роутера, решит повторить запрос и проведёт транзакцию дважды — это будет опять ваша вина.

Но даже не это главное. Допустим, ваши HTTP-пакеты гуляют в строго контролируемой среде. Как вы собираетесь объяснять другим разработчикам, какие рекомендации вы нарушили и почему? Как ваш коллега должен понять, что вот этот GET-запрос повторять нельзя, а статус 400 вовсе не означает клиентскую ошибку? Отступая от рекомендаций, вы, фактически, каждый раз создаёте какой-то свой диалект HTTP с собственной семантикой. Не забудьте его хотя бы задокументировать ;)

Список литературы:
www.rfc-editor.org/rfc/rfc2616.txt
tools.ietf.org/html/rfc5789
www.w3.org/TR/webarch
w3ctag.github.io/capability-urls

(В разработке последнего документа ваш покорный слуга принимал определённое участие.)
http, api, url, web-стандарты
+181 53596
1284forgotten 145,8
Похожие публикации

ObjectManager в API Яндекс.Карт. Как быстро отрисовать 10 000 меток на карте и не затормозить всё вокруг (88)
Как написать собственное приложение с REST API Яндекс.Диска (12)
Как правильно разрабатывать API с поддержкой обратной совместимости. Семинар в Яндексе (24)
Предложение от Яндекс.Денег в новом стандарте платежей W3C (32)
Открытая Yandex PHP Library для работы с API Яндекса (22)
Комментарии (82) отслеживать новые: в почте в трекере

+1 NiPh27 августа 2015 в 18:57#
Лаконично и понятно, спасибо за статью. Довольно часто приходится сталкиваться с мифом/немифом о том, что вообще не стоит использовать операции отличные от GET/POST/PUT/DELETE, мол не по стандарту это, с отсылкой как раз к промежуточным узлам которые могу отказаться не в курсе, и программистам на принимающей стороне, которые тоже могут быть не готовы, а в некоторых случаях — и вовсе не иметь инструментов для обработки таких запросов. В итоге вся логика которая в статье выкидывается на PATCH, например, запихивается в хитрый PUT. И так далее. В принципе, вся статья как бы намекает на ваше отношение к этому, но тем не менее — выскажитесь пожалуйста )
+8 forgotten27 августа 2015 в 19:01#↵↑
В 2015 году промежуточных узлов, не умеющих PUT/PATCH/DELETE, кажется, не осталось. Я, по крайней мере, не сталкивался.

В любом случае, есть стандартный механизм обхода таких ограничений: использовать GET/POST (первый в случае не изменяющих состояние ресурса операций, второй — для изменяющих), а нужный реально метод передавать заголовком X-HTTP-Method.
+9 Vanger1327 августа 2015 в 19:14#
Тема для холиваров на каждый день :)
По-сути на http хорошо ложится более-менее стандартный CRUD, вопросы начинаются с более сложными вещами.

Как вы обычно делаете (отображаете в HTTP API) query сущностей? А есть query возвращает данные по нескольким сущностям сразу? POST или GET для query? Odata, свой DSL или jquery format для параметров запроса? :)

Вы предлагаете «query» задавать как параметр запроса к сущности (../etntity/?query) т.е. в самом URL path глаголов быть не должно? Нам, вот, часто нужны глаголы и засовываем мы их именно в path (entity/copy, entity/prefetch, entity/lock). От части это связно с выбранной библиотекой HTTP: так удобнее писать роутеры — они биндятся на конкрутный path, а вот разделять по query param пришлось бы внутри каждого роута, что неудобно. Как и на чем вы пишете роутинг? И насколько разнообразны потребители вашего API в плане платформ\языков? У нас service'ы на scala, апотребители C#, C++, python, javascript и typescript и у каждого свои претензии что «что-то» делать недобно (например дописывать ID в середину path). :)

И в общем, в каких случаях вы позволяете себе отойти от следования рекомендациям по формированию пары method + URL?
+8 forgotten27 августа 2015 в 19:30#↵↑
> Тема для холиваров на каждый день :)

Не совсем.
Про REST-архитектуру действительно можно много холиварить, но пост-то не про неё, а про то, что нужно понимать смысл используемых сущностей — чем PUT отличается от POST, 400 от 500, ресурс от вызова метода. Здесь, в общем, разногласий быть не может: нравится тебе эта архитектура или нет, но Сеть работает именно так.

> Как вы обычно делаете (отображаете в HTTP API) query сущностей? А есть query возвращает данные по нескольким сущностям сразу? POST или GET для query? Odata, свой DSL или jquery format для параметров запроса? :)

> Вы предлагаете «query» задавать как параметр запроса к сущности (../etntity/?query) т.е. в самом URL path глаголов быть не должно? Нам, вот, часто нужны глаголы и засовываем мы их именно в path (entity/copy, entity/prefetch, entity/lock).

Вообще, в парадигме REST ответ на каждый из ваших запросов такой: создавайте специальный ресурс для каждого специфического требования.
Нужна мультиплексация? Значит, сделайте ресурс multiplexer.
Хотите избежать глагола в path? Сделайте ресурс: не GET /entity/prefetch, а GET /prefetcher/entity. И биндинги писать проще станет.
И так везде, где стандартной номенклатуры вам не хватает.
Я не могу дать универсальной рекомендации типа «всегда кладите query в query». Нужно смотреть на семантику конкретной операции и укладывать в HTTP-термины.

> И в общем, в каких случаях вы позволяете себе отойти от следования рекомендациям по формированию пары method + URL?

В целом, я вовсе не являюсь фанатом REST-архитектуры, многие вещи в неё ложатся плохо. Я категорически против смешения французского с нижегородским: если отходить от рекомендаций RFC — то полностью. Скажем, переходить на JSON-RPC или, прости господи, SOAP.

В реальности же постоянно наблюдаются адские кадавры, в которых перемешано всё, что можно.
+1 Encircled28 августа 2015 в 13:59#↵↑
Немного обидно за SOAP, за что вы его так? :) Свои задачи он решает достаточно хорошо
+1 Envek28 августа 2015 в 14:24#↵↑
Его просто почти никто не умеет правильно готовить. Когда появляется задача «синтегрироваться с вон теми ребятами, у них SOAP», то в 9 случаях из 10 не получится просто взять клиентскую SOAP-библиотеку и синтегрироваться. Обязательно что-то сделано… не так (вон, ниже привели пример про fault). И нужно наворачивать слои костылей. В общем, SOAP очень хорошо ассоциируется с болью и страданием.

Впрочем, если быть справедливыми, HTTP REST тоже мало кто умеет правильно готовить (с теми же вытекающими последствиями). Собственно, поэтому, видимо, и написали этот капитана пост.
0 Encircled28 августа 2015 в 14:32#↵↑
Логично, что при интеграции, если кто-то не соблюдает спецификацию, то вероятно где-то будет боль :)
+3 force27 августа 2015 в 19:36#
Такой вопрос: у нас есть метод, возвращающий текущее время (как пример). Логично, что он должен быть GET'ом, но при этом кешировать его явно не надо, ибо глупо. Решение в явном запрете кеширования со стороны сервера, или есть что-то умнее с учётом кеширования шарахалок по луне?
0 forgotten27 августа 2015 в 19:51#↵↑
В общем-то, можно придумать много решений, зависит от того, насколько важно всегда получать значение в обход кэша.

Вполне валидно в этой ситуации использовать POST, например, т.к. это метод с максимально широкой семантикой.
Можно обязать клиента приписывать к запросу время по его собственным часам и/или просто рандомное значение, тоже никто не запрещает.
На практике заголовков запрета кэширования от сервера обычно достаточно.
+1 force27 августа 2015 в 23:04#↵↑
POST — несемантично, рандомное значение — костыль. Но концепцию понял, волшебства тут нет :)
+1 force29 августа 2015 в 12:01#↵↑
Извините, я не специально, но только сейчас заметил, что у вас кешируется время на yandex.ru/internet :)

Скриншот
+1 force29 августа 2015 в 17:53#↵↑
Да, всё точно, ваш ответ про время закешировался, обновил браузер и получил
Скриншот
Идёт запрос на yandex.ru/internet/api/v0/datetime в ответе нет параметров кеширования. Мой вопрос оказался очень к месту, хотя был задан раньше, чем я увидел проблему у вас. :)
0 forgotten29 августа 2015 в 19:53#↵↑
Забавно.
Передам разработчикам )
0 artem_dev27 августа 2015 в 21:52#↵↑
Мы как-то для подобных случаев (у нас не должны были кешироваться динамические картинки) просто добавляли к таким URL параметр со случайным значением который ни на что не влиял.
+1 Alexeyslav28 августа 2015 в 00:11 (комментарий был изменён)#↵↑
Но тем не менее они все равно будут кешироваться забивая кеш бесполезными копиями…
т.е. перенесли проблему с больной головы на здоровую.
+3 Doomsday_nxt28 августа 2015 в 07:35 (комментарий был изменён)#↵↑
Ну если добавить еще заголовки запрета кэширования, то тот кто будет кэшировать (браузер, прокси и пр.) — ССЗБ.
0 tonymadbrain28 августа 2015 в 11:52#↵↑
Еще есть вариант с сохранением результата запроса на сервере или кодирование его в урле для последующей отдачи уже по другому ресурсу. К примеру:
1 запрос
2 запрос
+6 force28 августа 2015 в 12:08#↵↑
А это уже бредом попахивает. Конечно, семантичненько вышло, но накручивание могучей логики ради красоты семантики это уж слишком.
+1 441028 августа 2015 в 13:50#↵↑
В таких случаях предполагается использование заголовка Last-Modified.
+7 paranoik27 августа 2015 в 20:02#
Это был самый полезный Капитан Очевидность которого я когда-либо видел.
+1 forgotten27 августа 2015 в 20:03#↵↑
Стараемся ;)
0 Evengard27 августа 2015 в 20:19#
Прокси-сервера не очень охотно поддерживают что-то кроме get и post, особенно какие-нибудь корпоративные всеограничивающие.
+3 forgotten27 августа 2015 в 20:20#↵↑
Я таких давно уже не видел. В любом случае, специально для таких ситуаций придуман X-HTTP-Method.
habrahabr.ru/company/yandex/blog/265569/#comment_8552479
+4 dem0n3d27 августа 2015 в 20:24 (комментарий был изменён)#
10 пункт насилует логику. В заголовке написано что все что дальше — заблуждения. Т.е. в итоге получается что:
* 401 Unauthorized не обязан сопровождаться заголовком WWW-Authenticate (хотя выделение болдом намекает на обратное);
* статусы 3xx — это только редиректы;
* статус 404 клиент не имеет права повторять (кстати предложение сформулировано вообще неправильно: клиент имеет право повторять запрос а не статус).
+1 ivanych27 августа 2015 в 20:37#↵↑
Зашел написать этот комментарий.
+1 forgotten27 августа 2015 в 21:42#↵↑
Переформулировал.
–15 mtp27 августа 2015 в 20:53#
Где-то минимум трети написанного — субъективщина. Начиная с первого пункта и далее. Чем вам не нравится метод в запросе? Почему не /Луна/?who=шарахалка?

Якорь ещё зачем-то фрагментом обозвали. И про сортировку по породам — тоже спорный вопрос, многие интернет-магазины уже отошли от этой концепции нулевых и ссылаются на один и тот же монитор и как /monitors/HP/model, и как /HP/monitors/lcd/model, фильтры и теги вместо жесткой каталогизированной структуры.
+13 torkve27 августа 2015 в 21:01#↵↑
en.wikipedia.org/wiki/Fragment_identifier
tools.ietf.org/html/rfc3986#section-3.5

В RFC нет ни одного упоминания слова anchor.
+7 Sild27 августа 2015 в 21:25#↵↑
Не стоит брать за основу своих доводов некорректно написанные ядра интернет-магазинов. За разные запросы, возвращающие одинаковые сущности, можно и с поисковой выдачи улететь.
+11 forgotten27 августа 2015 в 21:51 (комментарий был изменён)#↵↑
> Где-то минимум трети написанного — субъективщина.

К рекомендациям RFC и IETF можно много претензий предъявлять, но уж точно не в плане субъективности.

> Почему не /Луна/?who=шарахалка?

Потому что ресурс — то, над чем выполняется действие. Стреляя из пушки, вы выполняете действие над пушкой, а не над Луной. К тому же, вряд ли у вас есть ресурс «Луна».

> Якорь ещё зачем-то фрагментом обозвали.

Это не я, это Тим Бёрнерс-Ли
tools.ietf.org/html/rfc3986#section-3.5

> И про сортировку по породам — тоже спорный вопрос, многие интернет-магазины уже отошли от этой концепции нулевых и ссылаются на один и тот же монитор и как /monitors/HP/model, и как /HP/monitors/lcd/model

Тем самым нарушая самый базовый принцип архитектуры Web из возможных.

Although there are benefits (such as naming flexibility) to URI aliases, there are also costs. URI aliases are harmful when they divide the Web of related resources. [...] Good practice: Avoiding URI aliases. A URI owner SHOULD NOT associate arbitrarily different URIs with the same resource.

www.w3.org/TR/webarch/#uri-aliases
+3 musuk27 августа 2015 в 20:59#
А если переделать фразу с Get на Post:
«да плевать я на всё это хотел, придумали какой-то ненужной ерунды; как у меня работали все сервисы только на POST, так и дальше будут, мучайтесь со своими PUT-ами и DELETE-ми сами».
То что в ней не так?
0 Godless27 августа 2015 в 21:22#↵↑
и это тоже крайность
+7 forgotten27 августа 2015 в 21:53#↵↑
Да практически всё.
— Нет кэширования.
— В условиях плохого соединения запросы повторять нельзя.
— При нажатии Back или Refresh браузер будет показывать сообщение «Подтвердите повторную отправку формы».
И так далее.
0 musuk28 августа 2015 в 11:30#↵↑
Если я делаю REST API для SPA или для мобильного приложения, то мне как раз не нужно кеширование.
Надеяться, что кто-то повторит мой запрос тоже как-то странно, для этого я делаю отдельный обработчик, хотя, тут, может и стоит заиспользовать GET.
Ну а проблема Back или Refresh для REST API не актуальна.
На счёт Get/Post понятно, но зачем усложнять REST API всякими PUT и DELETE, если достаточно POST и GET.
0 forgotten28 августа 2015 в 11:34 (комментарий был изменён)#↵↑
Вот как раз мобильное приложение — это то место, где *необходимо* использовать идемпотентные методы, поскольку мобильная сеть крайне ненадёжна, и любой запрос может отвалиться по таймауту (и при этом успешно выполниться на сервере).

Ну и как-то странно отказывать от кэширования в мобильном о_О
0 musuk28 августа 2015 в 12:55 (комментарий был изменён)#↵↑
Зачем в мобильном REST API использовать PUT, DELETE, CREATE и т.п. если можно обойтись POST и GET?
В чём реальный профит?
0 lair28 августа 2015 в 13:06#↵↑
Приблизительно в том же, в чем вообще профит от хорошей архитектуры — проще, понятнее, расширяемее.
+1 musuk28 августа 2015 в 13:22 (комментарий был изменён)#↵↑
«Хорошая архитектура» — слишком абстрактное понятие. Я предпочитаю конкретные вещи. Вроде того, что ответили выше про то, что GET-кешируемый и повторяемый. Ок, это может помочь достучаться до сервера. Хотя логику кеширования и обработки таймаутов и ошибок всё равно нужно писать на клиенте.

Вот, например, я реализовал публичный REST API, и мне надо чтобы клиенты могли им просто воспользоваться по простой доке и не трогали меня. По мне, так лучше предложить им 1 или 2 типа запроса, чем 5.
Как-то предложить людям постить JSON запрос на /FunctionName проще, чем заставлять их выставлять X-Header, тип запроса, а данные либо пихать в query, либо в body и прочее.
Kлиенты же потом прийдут мозг выносить: «почему мой запрос не проходит» из-за этой расширяемости архитектуры.
+1 lair28 августа 2015 в 13:37#↵↑
Вроде того, что ответили выше про то, что GET-кешируемый и повторяемый.

PUT тоже (может быть) повторяемый. И это очень удобно, когда вам надо создавать объект по нестабильному соединению.

Хотя логику кеширования и обработки таймаутов и ошибок всё равно нужно писать на клиенте.

Дело в том, что если вы используете стандартные средства, то можно найти стандартный же клиент, который будет их поддерживать, и тем самым упростить свою жизнь.

По мне, так лучше предложить им 1 или 2 типа запроса, чем 5.

Эти «типы запросов» потом где-то выражать. У вас есть выразительное средство, но вы им не пользуетесь.

Вот, например, я реализовал публичный REST API, [...] Как-то предложить людям постить JSON запрос на /FunctionName проще

Просто это больше не REST, вот и все.

Есть такая штука — семантика. Вот вы ее нарушаете. Человеку, который привык к нормальным REST API будет сложно понять, что у вас происходит, и как этим пользоваться. Это как в SOAP вместо fault возвращать обычный ответ с кодом ошибки.
+11 berman27 августа 2015 в 22:03#

+1 tenbits27 августа 2015 в 22:11#
Вот меня уже давно мучает вопрос по custom http codes. При ошибках нам всегда нужно приложению отдавать конкретный номер ошибки, сейчас отдаем более подходящий стандартный http статус, а в теле ответа уже код конкретной ошибки. Боюсь за неадекватное поведение разных прокси у клиентов. Но такое дублирование разных кодов, сначала в заголовках, а потом в теле мне не совсем нравится. Есть у кого-то идеи по этому поводу или даже опыт работы с пользовательскими статусами?
+6 forgotten27 августа 2015 в 22:18#↵↑
Чтобы ответить на ваш вопрос, требуется конкретика. Почему вас не устраивает стандартная номенклатура http-кодов?

Если у вашего ресурса есть какая-то своя внутренняя номенклатура ошибок, то никто не мешает отвечать статусом 400 или 500 (в зависимости от того, клиентская ли ошибка) и отдавать в теле ответе, скажем, JSON с описанием произошедшей ошибки (в т.ч. внутренним кодом). Однако в такой ситуации я бы рекомендовал работать по RPC-протоколам, т.е. использовать HTTP как транспорт и отвечать строго 200.
0 tenbits27 августа 2015 в 23:22#↵↑
Не хотел приводить конкретный пример, что бы не обсуждать частный случай. Но представьте, у нас есть игра, и некий ресурс, который возвращает актуальный статус игры: Фаза1, 2… 10. Хотелось бы, например, возвращать коды 251, 252… 260 соответственно. Тогда даже простым HEAD запросом можно уже знать состояние. Или другая ситуация с ошибкой валидации запроса: 471 — неверный параметр «А», 472 — конфликт значения «Б», и т.д.

никто не мешает отвечать статусом 400 или 500 (в зависимости от того, клиентская ли ошибка) и отдавать в теле ответе, скажем, JSON

Мы так и делаем сейчас, другого варианта пока нет. Но повторюсь, что конкретный статус непосредственно в заголовках мне кажется лучше, ведь а) можно HEAD запросом уже получить состояние и б) не нужно повторяться (один код в заголовках, и другой код в теле).

Но к сожалению на данный момент нет общепринятого промежутка для пользовательских статусов, например 45X-49X;55X-59X;7XX-9XX;, или другой способ: конкретный номер через точку:400.ХХХ.

+5 alekciy27 августа 2015 в 23:31#↵↑
Наверное что-то не уловил, но почему не использовать X-Status?
0 tenbits27 августа 2015 в 23:49#↵↑
Да, это действительно отличный вариант! Не хочу писать это слово, «но» это уже из области пользовательских заголовков. А работа лишь с http статусом была бы предпочтительнее.
+7 torkve28 августа 2015 в 00:10#↵↑
Почему? Ведь HTTP-статус — это «транспортная» часть, статус доступа. А Вы хотите отдавать логическую часть приложения, смешать два уровня.
0 tenbits28 августа 2015 в 02:37#↵↑
Согласен, так оно и есть. Но на данный момент, мне кажется, это вовсе не два изолированных уровня, особенно в контексте API ресурсов, ведь за частую, как раз приложение решает или это Bad Request, или Conflict, или что-то там ещё. Выходит эти уровни уже давно смешаны. Поэтому пора бы уже сделать окончательное смешивание.
+6 forgotten28 августа 2015 в 08:35#↵↑
torkve совершенно прав, так делать ни в коем случае не надо.
HTTP статусы должны индицировать статус самого обращения по HTTP. Если HTTP — просто транспорт до некоторого программного endpoint-а, то номенклатура HTTP-статусов должна описывать строго транспортную часть. 200 — запрос дошел и обработан endpoint-ом (независимо от успешности и состояния такой обработки), 4xx — запрос сформирован неправильно и до endpoint-а не дошёл, 500 — ошибка сети или веб-сервера (т.е. обработчика HTTP-запросов, не самого endpoint-а).
0 tenbits28 августа 2015 в 13:34#↵↑
Неужели никто никогда не меняет напрямую, или косвенно статус код ответа в самом приложении? Если «нет», то тут вы меня удивите, а если «да», то речи о разделении транспорта и приложения уже быть не может. Или мы как-то друг друга не верно понимаем? Или ещё пример: Если endpoint по фазе луны определил что запрос не верный, неужели статус не измените на 400?
0 forgotten28 августа 2015 в 14:10#↵↑
> Неужели никто никогда не меняет напрямую, или косвенно статус код ответа в самом приложении?

Ммм, это как?

> Если endpoint по фазе луны определил что запрос не верный, неужели статус не измените на 400?

Нет.
HTTP статусы — для ошибок уровня протокола HTTP.
Вас же не удивляет, что TCP не знает про ошибки HTTP, и статус его пакетов «ок», даже если в них передаётся закодированная 500-ая ошибка HTTP? Так и в вашем случае. HTTP отработал валидно — статус 200.
0 tenbits28 августа 2015 в 14:39#↵↑
> Неужели никто никогда не меняет напрямую, или косвенно статус код ответа в самом приложении?
Ммм, это как?

Response.StatusCode = HttpStatusCode.BadRequest;
// или через exception
throw new HttpBadRequest(message);
// или ещё другими 100500 способами.

> Если endpoint по фазе луны определил что запрос не верный, неужели статус не измените на 400?
Нет.
Интересно, как же по вашему в этом случае приложение должно получить и отреагировать на ошибку (если мы говори о RESTful запросах и json формате)? lair упоминает о адекватном использовании существующих статусов. И действительно, все так делают, вы наверное первый от кого я слышу, что нельзя в приложении менять статус на 400, например.

lair, «адекватно-не-адекватно» это в любом случае «использование» в целях приложения, и я к тому и веду, что раз мы уже используем статусы, то чисто из мышления программиста у меня возник вопрос, ведь это абсолютно не DRY менять http-status, и ещё! дополнительно! передавать конкретный статус или в кастомном заголовке, или же где-то в теле ответа. И клиент тоже соответственно должен реагировать на http статус, a потом ещё на конкретный статус ответа.
0 forgotten28 августа 2015 в 14:45#↵↑
Здесь какое-то недопонимание.

Если у вас REST-приложение, оно *обязано* отвечать HTTP-статусами, соответствующими типу ошибки.

Если у вас не-REST (JSON-RPC, SOAP, whatever) приложение, то good practice — отвечать не-200 статусами только в случае проблем самого HTTP-протокола (сетевые ошибки, веб-сервер упал). Все ошибки внутреннего состояния сервиса кодируются в соответствующий (JSON, XML) формат и возвращаются с HTTP-статусом 200.
0 soniq28 августа 2015 в 18:00#↵↑
Читал-читал ваш диалог, и окончательно запутался с REST и кодами ответа.

При запросе, например, профиля пользователя по id возможны варианты:

1. Пользователь найден, статус ответа 200, в теле ответа профиль в формате xml. Семантика xml описывается в доке на API.
2. Пользователь удален, статус 410, тело ответа пустое
3. Такой пользователь никогда не был зарегистрирован, статус 404, тело ответа пустое
4. Этот профиль запрашивающему смотреть нельзя, ответ 403
5. Пользователь в отпуске, отвечаем 303 и id заместителя

По-моему, это ерунда какая-то?
0 lair28 августа 2015 в 18:06#↵↑
Если вы про REST, то никакой особой ерунды (разве что последнее вызывает у меня сомнения — во-первых, должен быть не ID, а Location, а во-вторых, что важнее, я не уверен, что семантика 303 совпадает с семантикой «замещения»).
0 soniq28 августа 2015 в 22:21#↵↑
Ерунда тут в том, что таким подходом можно описать только работу с чем-то, очень похожим на файловую систему: ссылки, каталоги, права доступа, вот это все, а содержимое файлов — просто блоб. Можно, конечно, притвориться, что наши сервисы (как профили пользователей в моем примере) — это такие хитрые ресурсы, но тогда от REST в такой схеме ничего не остается.
+1 lair29 августа 2015 в 00:41#↵↑
Зачем притворяться? Профили — и правда ресурсы, а то, что вы называете «файловой системой» — всего лишь иерархически организованные ресурсы с перекрестными ссылками. И это вполне понятное человеку структурирование домена.

Кстати, почему же содержимое — просто блоб? Нет, отнюдь, это гипермедиа.
0 lair28 августа 2015 в 14:45#↵↑
ведь это абсолютно не DRY менять http-status, и ещё! дополнительно! передавать конкретный статус или в кастомном заголовке, или же где-то в теле ответа.

Почему же? Это типичная ситуация статуса и сабстатуса. Один клиент будет разбирать тело, другой — нет, но оба они получат ошибочный статус верхнего уровня и не будут считать сообщение успешным.
0 tenbits28 августа 2015 в 13:40#↵↑
Выше я имел ввиду именно RESTful подход, не RPC, SOAP
0 lair28 августа 2015 в 14:18#↵↑
Вообще, это вы странное сейчас описываете. Так (разделяя транспорт и бизнес) действительно делали в SOAP, а вот в REST так не делают. REST признает HTTP-протокол и использует его статусы для описания своего состояния.

Это не повод, конечно, заводить собственные статусы, но вот адекватно использовать существующие — например, 500 при любой серверной ошибке, которую мы согласились разглашать, или 400 в случае ошибки валидации, или 409, если изменилось состояние объекта для модификации — вполне разумно и адекватно.
0 forgotten28 августа 2015 в 14:25#↵↑
Не очень понимаю, о чём вы. REST — это как раз предложенная идеологами HTTP архитектура веб-приложений, полностью на HTTP основанная. Разумеется, REST-сервис должен полностью и строго следовать описанным в стандарте принципам.

Я пишу ровно о том, что правильно или делать приложение в REST-парадигме, полностью следуя семантике HTTP; или делать приложение в другой архитектуре, например, SOAP или JSON-RPC, но тогда ни в коем случае не нужно смешивать статусы высокоуровневых операций с низкоуровневыми. HTTP 500 и HTTP 200 передаются через TCP совершенно одинаково, никто не пытается HTTP-статусы спустить на уровень TCP. Так же и ваше приложение поверх HTTP не должно использовать HTTP-статусы для индицирования своего высокоуровневого состояния.
0 lair28 августа 2015 в 14:27#↵↑
Окей, признаю, не отследил момент, когда вы предложили отказаться от REST и перейти на RPC-over-HTTP. В этом случае, действительно, вы правы (другое дело, что я не могу найти достаточно мотивирующих факторов для такого перехода, но это тема другого обсуждения).
0 alekciy28 августа 2015 в 15:17#↵↑
Поскольку REST признает HTTP-протокол и использует его состояние, то он не исключает использование и собственных заголовков, ведь HTTP не запрещает этого делать (ну кроме префикса X- который записали в старевший).

Конечно приложение должно максимально использовать существующие статусы, но если логика приложения требует своих, то ни что не мешает их добавить. Просто отражать они должны нужные состояние приложения, а не соединения.
0 alekciy28 августа 2015 в 15:27#↵↑
Вопрос с подковыркой. Где в приведенных примерах 3хх?
Я к тому, что endpoint как именно конечно точка htpp взаимодействия может и сам отвечать статусами.
0 forgotten28 августа 2015 в 15:33#↵↑
3xx в этой ситуации возможен, кажется, только в случае переезда endpoint-а за другой URL
0 alekciy28 августа 2015 в 15:39#↵↑
На вскидку 304. Веб сервер без участия endpoint не знает, можно ли так ответить (мы же говорим про приложение, т.е. запросы динамические и это не статика в ФС в которую веб сервер может сходить и сам).
0 forgotten28 августа 2015 в 15:53#↵↑
Как правильно должно выглядеть такое взаимодействие:

клиент: POST /resource/
{ «method»: «getNyashnyKotikNextPhoto», «ifModifiedSince»: <таймстэмп> }
сервер: 200 OK
в теле либо { «notModified»: true }, либо фотка няшного котика

Неправильно:
клиент: GET /resource/?method=getNyashnyKotikNextPhoto
If-Modified-Since: <таймстэмп>
Сервер: 200 OK или 304 Not Modified

Почему так неправильно: потому что ручка resource обладает внутренней семантикой, неизвестной протоколу HTTP. В данном примере — сервер не только отдаёт/не отдаёт картинку, но и смещает внутренний указатель (getNextPhoto).

Соответственно, возможны практически любые спецэффекты. Например, где-то прокси может закэшировать ответ, и фоточки котиков не будут листаться.

Я специально подобрал такой пример, конечно. Но, если у вашей ручки нет внутренней семантики, не ложащейся в HTTP — значит, можно строго по HTTP и работать. А если она есть, то на подобные грабли вы обязательно и наступите.
0 alekciy28 августа 2015 в 15:42#↵↑
Ну и 1хх тоже остались охвачены. 102 без бэкнда никуда.
+1 milast28 августа 2015 в 12:50#
Мне так не ясен один вопрос. Если HTTP имеет методы GET, POST, PUT, DELETE и другие, почему же в самом HTML в теге FORM могут присутствовать только два метода: GET и POST?
0 Ununtrium28 августа 2015 в 13:01#↵↑
легаси?
+6 forgotten28 августа 2015 в 14:07#↵↑
Вероятно, потому, что HTTP и HTML — разные вещи, и их даже разрабатывают три разные организации.
0 Spoofi28 августа 2015 в 14:29#
Отличная статья, спасибо кэпу :)

Но у меня есть вопрос: где посмотреть реальный пример, где все эти методы реализованы и правила соблюдаются?
Мне вот, например, не доводилось использовать такой API :)
0 Envek28 августа 2015 в 14:38#↵↑
У GitHub'а весьма недурной API, я думаю, что там выдержаны как минимум почти все пожелания из этого поста (кроме Capability URL, но они не к API относятся, а к веб-интерфейсу): developer.github.com/v3
0 Spoofi28 августа 2015 в 14:43#↵↑
Спасибо, посмотрю. Как обычно, все под носом, но не заметно :)
+2 forgotten28 августа 2015 в 14:47#↵↑
REST API Диска, например, почти полностью по стандарту.
tech.yandex.ru/disk/poligon/#!//v1/disk/resources
+1 maxvoloshin 1 сентября 2015 в 08:51#↵↑
Было бы круто чтобы API Яндекс.Директ и Яндекс.Маркет также можно было показать в пример к этой статье :)
+5 OlegTar28 августа 2015 в 14:51#↵↑
Видимо API какого-то из сервисов Яндекса.
–4 velikan528 августа 2015 в 16:02#
Опять полное непонимание, что такое URL/URI/URN… бррр
И это в Яндексе?
+6 forgotten28 августа 2015 в 16:05#↵↑
Что, простите?
0 Diokuz28 августа 2015 в 19:33#
Последний абзац можно отнести к любым стандартам и соглашениям — они для того и есть, чтоб все понимали друг друга.
+1 kemsky30 августа 2015 в 02:22#
Советы полезные — спору нет, но все же вброшу немного.
0 potan31 августа 2015 в 12:13#
Оформить бы эти рекомендации в виде онтолигии… Или, хотя бы, таблички.
0 forgotten31 августа 2015 в 12:13#↵↑
Дерзайте.
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 5 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

Linux tcp programming

#9 dyvniy » Пт, 4 декабря 2015, 20:53:07

http://www.tenouk.com/Module43a.html
Спойлер
пока пусто
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 5 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#10 dyvniy » Вс, 4 июня 2017, 21:31:42

proxy зкщчн
например kinogo.co
frigate
https://chrome.google.com/webstore/detail/frigate-light/
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 5 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#11 dyvniy » Чт, 24 марта 2022, 10:49:35

курл или сиюэрэл
https://ru.howtopronounce.com/curl
Изображение


Название раздела: Web на стороне клиента, Java Script
Описание: Наиболее перспективное направление развития компьютерных наук. Надо быть в теме!

Быстрый ответ


Введите код в точности так, как вы его видите. Регистр символов не имеет значения.
Код подтверждения
:) ;) :hihi: :P :hah: :haha: :angel: :( :st: :_( :cool: 8-| :beee: :ham: :rrr: :grr: :* :secret: :stupid: :music: Ещё смайлики…
   

Вернуться в «Web на стороне клиента, Java Script»

Кто сейчас на форуме (по активности за 15 минут)

Сейчас этот раздел просматривают: 5 гостей