캐싱을 위해 ETag 및 조건부 헤더를 사용하는 방법에 대한 자세한 설명
Laravel API 성능 최적화: ETag 및 조건부 헤더를 사용한 캐싱
별도의 프런트엔드와 백엔드로 애플리케이션을 작성할 때 프런트엔드 클라이언트가 백엔드에서 데이터를 다시 가져오기 위해 어떤 종류의 요청을 API에 제출할지 생각해야 합니다. 실시간으로 업데이트되는 추가된 데이터를 프런트엔드 캐시가 처리할 수 있는지 확인하고 싶습니다. 위의 요구 사항에 따라 ETag
헤더와 조건부 요청을 사용할 수 있습니다. ETag
头 和 conditional requests。
在这篇博文中,我会简单的概括一下 ETag
, If-None-Match
和 If-Match
头是做什么的,然后再看看我是如何将这些应用到我们的package中的,这个软件包可以快速的将它实施到您的应用程序中。
是什么
让我们从这一切的核心内容开始,那就是 ETag
头。该头文件是表示其所在的确切状态下的响应主体的值。在很多情况下 ETag
的值将是内容的 hash
值,因为这是最容易生成和保证响应数据唯一性标识符的方法。
为了保证 ETag
头可用,我们必须使用条件请求。我们需要设置的第一个条件是 If-None-Match
头,这是一个用于 GET
的请求头。在后端接收到这个头之后,需要将它和当前的内容进行比较。如果值匹配的话,将只返回 304
状态码,和获取实体资源比较起来,响应结果的数据本身是很小的。这一切实施起来是非常简单的:如果你的第一个获取资源的 GET
请求返回了一个 ETag
数据,你的浏览器会自动的为接下来的资源的请求配置 If-None-Match
头。
这意味着,如果您的后端简单实现了 etag
和 if-none-match
,则可以减少从您的API传输到前端的数据量。
第二个请求条件使用的是 if-match
头。这被用来阻止 mid-air collisions 。 通俗的说,如果我们想要在后端更新数据,但是我们的前端数据已经过时,后端的更新应该被终止,而且前端也应该有提醒。 这和 if-none-match
的工作方式很类似。在获取到包含 ETag
值的资源之后,你可以提交一个 PATCH
请求并且设置一个和你之前接收到的 ETag
值相等的 If-Match
值。然后,后端将检查服务端当前可用的资源的 etag
值是否与您发送的资源相匹配。如果匹配,将允许您的更新。如果没有匹配,将返回412
状态码,让前端知道条件不匹配。
如何使用
如果你想要在 laravel
项目中使用这个条件请求插件包的话,你可以使用以下命令来安装:
$ composer require werk365/etagconditionals
然后在你的路由中添加 etag
中间件之后就可以使用了。如果你想研究中间件的工作原理,或者想要不通过我们的插件包来实现这个功能的话,请接着往下读!
SetEtag 中间件
正如您可能已经猜到的那样,我们可以通过中间件来很简单的实现这一功能。 Laravel
实际上已经为我们提供了一个 SetCacheHeaders
中间件来设置 ETag
头, 但是它不支持 HEAD
请求。 SetEtag
中间件的内容看起来是这样的:
public function handle(Request $request, Closure $next) { // Handle request $method = $request->getMethod(); // Support using HEAD method for checking If-None-Match if ($request->isMethod('HEAD')) { $request->setMethod('GET'); } //Handle response $response = $next($request); // Setting etag $etag = md5($response->getContent()); $response->setEtag($etag); $request->setMethod($method); return $response; }
我们首先要做的事情是获取请求的方法,以防我们想要修改它。然后,当我们在处理 HEAD
请求的时候,我们把它修改为 GET
请求,以确保请求的内容已经被加载而且可以被加密。在此之后,我们跳转到已经使用 md5()
方法加密后的响应主体内容。在返回响应之前,我们会将加密后的 hash
值作为 ETag
ETag
, If-None-Match
및 If-Match
헤더의 기능을 간략하게 요약한 다음 이를 패키지에 어떻게 적용했는지 살펴보세요. 이를 통해 애플리케이션에 빠르게 구현할 수 있습니다. 무엇입니까
모든 것의 핵심인 ETag
헤더부터 시작하겠습니다. 이 헤더는 응답 본문의 정확한 상태를 나타내는 값입니다. 대부분의 경우 ETag
값은 콘텐츠의 hash
값이 됩니다. 이는 응답 데이터에 대한 고유 식별자를 생성하고 보장하는 가장 쉬운 방법이기 때문입니다. ETag
헤더를 사용할 수 있도록 하려면 조건부 요청을 사용해야 합니다. 우리가 설정해야 할 첫 번째 조건은 GET
에 사용되는 요청 헤더인 If-None-Match
헤더입니다. 백엔드는 이 헤더를 수신한 후 이를 현재 콘텐츠와 비교해야 합니다. 값이 일치하면 304
상태 코드만 반환됩니다. 엔터티 리소스를 얻는 것에 비해 응답 결과 데이터 자체는 매우 작습니다. 이 모든 것은 구현하기가 매우 간단합니다. 리소스에 대한 첫 번째 GET
요청이 ETag
데이터를 반환하는 경우 브라우저는 자동으로 리소스의 요청 구성 If-None-을 수행합니다.
헤더와 일치합니다. 🎜🎜즉, 백엔드에서 etag
및 if-none-match
만 구현하면 API에서 프런트엔드로 전송되는 데이터의 양을 줄일 수 있다는 의미입니다. 🎜🎜두 번째 요청 조건은 if-match
헤더를 사용합니다. 이는 🎜공중 충돌🎜을 방지하는 데 사용됩니다. 일반인의 관점에서 볼 때, 백엔드에서 데이터를 업데이트하고 싶지만 프런트엔드 데이터가 오래된 경우 백엔드 업데이트가 종료되어야 하며 프런트엔드에 미리 알림이 있어야 합니다. 이는 if-none-match
작동 방식과 유사합니다. ETag
값이 포함된 리소스를 검색한 후 PATCH
요청을 제출하고 ETag
값을 이전에 받은 값과 동일하게 설정할 수 있습니다. code>If-Match 값. 그런 다음 백엔드는 서버에서 현재 사용 가능한 리소스의 etag
값이 보낸 리소스와 일치하는지 확인합니다. 일치하는 항목이 있으면 업데이트가 허용됩니다. 일치하는 항목이 없으면 412
상태 코드가 반환되어 프런트 엔드에 조건이 일치하지 않음을 알립니다. 🎜사용 방법
🎜laravel
프로젝트에서 이 조건부 요청 플러그인 패키지를 사용하려면 다음 명령을 사용하여 설치할 수 있습니다. 🎜public function handle(Request $request, Closure $next) { // Handle request $method = $request->getMethod(); // Support using HEAD method for checking If-None-Match if ($request->isMethod('HEAD')) { $request->setMethod('GET'); } //Handle response $response = $next($request); $etag = '"'.md5($response->getContent()).'"'; $noneMatch = $request->getETags(); if (in_array($etag, $noneMatch)) { $response->setNotModified(); } $request->setMethod($method); return $response; }
etag
미들웨어를 추가한 후 사용할 수 있습니다. 미들웨어 작동 방식을 연구하고 싶거나 플러그인 패키지를 사용하지 않고 이 기능을 구현하고 싶다면 계속 읽어보세요! 🎜🎜SetEtag Middleware🎜🎜 짐작하셨겠지만 미들웨어를 통해 이 기능을 쉽게 구현할 수 있습니다. Laravel
은 실제로 ETag
헤더를 설정하기 위한 SetCacheHeaders
미들웨어를 제공하지만 HEAD
요청을 지원하지 않습니다. SetEtag
미들웨어의 내용은 다음과 같습니다: 🎜public function handle(Request $request, Closure $next) { // 只有请求方式是 PATCH 并且已经设置了 If-Match 头 if (! ($request->isMethod('PATCH') && $request->hasHeader('If-Match'))) { return $next($request); } // 对同一个点创建新的 GET 请求, // 复制和添加请求头,让中间件能忽略本次请求 $getRequest = Request::create($request->getRequestUri(), 'GET'); $getRequest->headers = $request->headers; $getRequest->headers->set('X-From-Middleware', 'IfMatch'); $getResponse = app()->handle($getRequest); // Get content from response object and get hashes from content and etag $getContent = $getResponse->getContent(); $getEtag = '"'.md5($getContent).'"'; $ifMatch = $request->header('If-Match'); // 比较当前和请求携带的 hash 值 if ($getEtag !== $ifMatch) { return response(null, 412); } return $next($request);
HEAD
요청을 처리할 때 요청된 콘텐츠가 로드되었고 암호화될 수 있는지 확인하기 위해 이를 GET
요청으로 수정합니다. 그런 다음 md5()
메서드를 사용하여 암호화된 응답 본문 콘텐츠로 이동합니다. 응답을 반환하기 전에 암호화된 hash
값을 ETag
헤더로 사용하고 원래 요청 방법을 다시 설정합니다. 🎜🎜IfNoneMatch 미들웨어 🎜🎜이것은 비교적 간단한 또 다른 방법입니다. 먼저 코드를 살펴보겠습니다: 🎜public function handle(Request $request, Closure $next) { // Handle request $method = $request->getMethod(); // Support using HEAD method for checking If-None-Match if ($request->isMethod('HEAD')) { $request->setMethod('GET'); } //Handle response $response = $next($request); $etag = '"'.md5($response->getContent()).'"'; $noneMatch = $request->getETags(); if (in_array($etag, $noneMatch)) { $response->setNotModified(); } $request->setMethod($method); return $response; }
这个开头与 SetEtag
中间件相似,将确保我们可以再次处理 HEAD
请求,并根据响应内容生成 hash值。注意这种情况下我们需要将hash值用双引号包裹。双引号包裹 ETag
头,然后在setEtag中间件中 setEtag()
方法自动包裹hash。有了hash值后,我们可以轻松的与 If-None-Match
头进行比较。由于该头可以自动加载无限个hash,并且 getETags()
方法会将它们以数组形式返回,所以我们可以核对新生成的值是否存在于数组中。如果确实有匹配,我们可以在响应中使用 setNotModified()
设置 304
的状态码。
IfMatch 中间件
处理 If-Match
将稍微复杂一些。这个问题归结于:我们需要找到一种方法,用来获取应该更新的当前版本的内容。这可以用多种方式实现。
- 你可以使用 HTTP 客户端对相同资源从外部发起
GET
请求 - 你可以查看当前请求将执行的操作, 而不是调用与之等价的
GET
请求( 例如,调用控制器上的show()
方法) - 或者你可以通过内部发起一个新的
GET
请求。
在构建这个中间件时,我开始尝试使用第二个选项。出于某种原因,这对我来说似乎是最好的选择。我成功地创建了一个完全可以工作的版本,但我对结果并不满意。为了让它工作,我需要做一些假设,预设一些限制,并做了太多的工作,而我只需要创建一个新的请求就可以了。
当我们要发起一个新的请求来获取当前版本资源的时候,代码是下面这样的:
public function handle(Request $request, Closure $next) { // 只有请求方式是 PATCH 并且已经设置了 If-Match 头 if (! ($request->isMethod('PATCH') && $request->hasHeader('If-Match'))) { return $next($request); } // 对同一个点创建新的 GET 请求, // 复制和添加请求头,让中间件能忽略本次请求 $getRequest = Request::create($request->getRequestUri(), 'GET'); $getRequest->headers = $request->headers; $getRequest->headers->set('X-From-Middleware', 'IfMatch'); $getResponse = app()->handle($getRequest); // Get content from response object and get hashes from content and etag $getContent = $getResponse->getContent(); $getEtag = '"'.md5($getContent).'"'; $ifMatch = $request->header('If-Match'); // 比较当前和请求携带的 hash 值 if ($getEtag !== $ifMatch) { return response(null, 412); } return $next($request);
所有这些中间件都将在请求生命周期开始时运行。首先,我们将过滤掉任何非 PATCH
请求或请求头中没有 If Match
的请求。之后,我们将向同一个端点发出一个新的 GET
请求,并从原来的请求中复制请求头,以便新请求可以通过身份验证中间件和其他约束。
使用这个新请求的响应,我们将再次生成一个哈希,以便与发送的哈希进行比较。如果哈希匹配,请求将被中间件允许通过。如果不匹配,将返回状态代码为 412
的请求响应。
通过使用这三个中间件,你可以在你的 Laravel 应用程序中轻松处理 ETag 和条件请求。
软件包:https://github.com/365Werk/etagconditionals
原文地址:https://hergen.nl/caching-your-laravel-api-with-etag-and-conditional-requests
译文地址:https://learnku.com/laravel/t/55539
위 내용은 캐싱을 위해 ETag 및 조건부 헤더를 사용하는 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Laravel 9 및 CodeIgniter 4의 최신 버전은 업데이트된 기능과 개선 사항을 제공합니다. Laravel9은 MVC 아키텍처를 채택하여 데이터베이스 마이그레이션, 인증, 템플릿 엔진 등의 기능을 제공합니다. CodeIgniter4는 HMVC 아키텍처를 사용하여 라우팅, ORM 및 캐싱을 제공합니다. 성능면에서는 Laravel9의 서비스 제공자 기반 디자인 패턴과 CodeIgniter4의 경량 프레임워크가 뛰어난 성능을 제공합니다. 실제 애플리케이션에서 Laravel9은 유연성과 강력한 기능이 필요한 복잡한 프로젝트에 적합한 반면, CodeIgniter4는 빠른 개발 및 소규모 애플리케이션에 적합합니다.

Laravel과 CodeIgniter의 데이터 처리 기능을 비교해 보세요. ORM: Laravel은 클래스-객체 관계형 매핑을 제공하는 EloquentORM을 사용하는 반면, CodeIgniter는 데이터베이스 모델을 PHP 클래스의 하위 클래스로 표현하기 위해 ActiveRecord를 사용합니다. 쿼리 빌더: Laravel에는 유연한 체인 쿼리 API가 있는 반면, CodeIgniter의 쿼리 빌더는 더 간단하고 배열 기반입니다. 데이터 검증: Laravel은 사용자 정의 검증 규칙을 지원하는 Validator 클래스를 제공하는 반면, CodeIgniter는 내장된 검증 기능이 적고 사용자 정의 규칙을 수동으로 코딩해야 합니다. 실제 사례: 사용자 등록 예시에서는 Lar를 보여줍니다.

초보자의 경우 CodeIgniter는 학습 곡선이 더 완만하고 기능이 적지만 기본적인 요구 사항을 충족합니다. Laravel은 더 넓은 기능 세트를 제공하지만 학습 곡선이 약간 더 가파릅니다. 성능면에서는 Laravel과 CodeIgniter 모두 좋은 성능을 보입니다. Laravel은 보다 광범위한 문서와 적극적인 커뮤니티 지원을 제공하는 반면 CodeIgniter는 더 간단하고 가벼우며 강력한 보안 기능을 갖추고 있습니다. 블로그 애플리케이션을 구축하는 실제 사례에서 Laravel의 EloquentORM은 데이터 조작을 단순화하는 반면 CodeIgniter는 더 많은 수동 구성이 필요합니다.

Laravel - Artisan Commands - Laravel 5.7은 새로운 명령을 처리하고 테스트하는 새로운 방법을 제공합니다. 여기에는 장인 명령을 테스트하는 새로운 기능이 포함되어 있으며 데모는 아래에 언급되어 있습니다.

대규모 프로젝트를 위한 프레임워크를 선택할 때 Laravel과 CodeIgniter는 각각 고유한 장점을 가지고 있습니다. Laravel은 엔터프라이즈급 애플리케이션을 위해 설계되었으며 모듈식 디자인, 종속성 주입 및 강력한 기능 세트를 제공합니다. CodeIgniter는 속도와 사용 편의성을 강조하여 중소 규모 프로젝트에 더 적합한 경량 프레임워크입니다. 요구 사항이 복잡하고 사용자 수가 많은 대규모 프로젝트의 경우 Laravel의 성능과 확장성이 더 적합합니다. 간단한 프로젝트나 리소스가 제한된 상황에서는 CodeIgniter의 가볍고 빠른 개발 기능이 더 이상적입니다.

소규모 프로젝트의 경우 Laravel은 강력한 기능과 보안이 필요한 대규모 프로젝트에 적합합니다. CodeIgniter는 가볍고 사용하기 쉬운 매우 작은 프로젝트에 적합합니다.

Laravel의 Blade와 CodeIgniter의 Twig 템플릿 엔진을 비교해 보면 프로젝트 요구 사항과 개인 선호도에 따라 선택하십시오. Blade는 MVC 구문을 기반으로 하므로 좋은 코드 구성과 템플릿 상속을 장려합니다. Twig는 유연한 구문, 강력한 필터, 확장된 지원 및 보안 샌드박스를 제공하는 타사 라이브러리입니다.

Laravel - Artisan Console - Laravel 프레임워크는 명령줄을 통한 상호 작용을 위한 세 가지 기본 도구인 Artisan, Ticker 및 REPL을 제공합니다. 이번 장에서는 Artisan에 대해 자세히 설명합니다.
