IETF HTTP Çalışma Grubu, QUERY adında yeni bir HTTP istek metodu tanımladı (draft-ietf-httpbis-safe-method-w-body, RFC olma yolunda ilerliyor). QUERY, her REST geliştiricisinin karşılaştığı bir boşluğu dolduruyor: GET gibi güvenli ve idempotent bir istek, ancak POST gibi bir istek gövdesi taşıyor. sgcWebSockets artık QUERY'yi uçtan uca destekliyor: HTTP/1.1, HTTP/2 ve HTTP/3 istemcilerinde ve sunucu bileşenlerinde, Delphi ve C++ Builder için.
Neden yeni bir HTTP metodu?
Şimdiye kadar bir sunucuya sorgu göndermenin iki yolu vardı ve ikisinin de sorunları var. Sorguyu bir GET isteğinin URL'sine kodlayabilirsiniz, ancak URL'lerin pratik uzunluk sınırları vardır, karmaşık sorguları kaçış karakterleriyle yazmak zahmetlidir ve tam URL genellikle proxy ve sunucu günlüklerine düşer ki burası hassas filtre değerleri için kötü bir yerdir. Ya da sorguyu bir POST isteğinin gövdesinde gönderebilirsiniz, ancak POST güvenli değildir, idempotent değildir ve önbelleğe alınamaz: bir HTTP istemcisinin bağlantı hatasından sonra isteği otomatik olarak yeniden denemesine izin verilmez ve önbellekler yanıtı saklamaz.
QUERY her ikisinin de en iyi yanlarını birleştiriyor. İstek içeriği ve Content-Type başlığı sorguyu tanımlar, bu nedenle sorgu gerektiği kadar büyük ve yapılandırılmış olabilir (form verisi, JSON, SQL, JSONPath, sunucu neyi kabul ediyorsa). Aynı zamanda spesifikasyon QUERY'yi güvenli ve idempotent olarak tanımlar: kaynağın durumunu asla değiştirmez, güvenle yeniden denenebilir veya tekrarlanabilir ve yanıtları tıpkı bir GET yanıtı gibi önbelleğe alınabilir.
QUERY nasıl çalışır
Bir QUERY isteği, GET semantiğine sahip bir POST gibi görünür. Spesifikasyondan uyarlanan bu örnek, bir kişiler kaynağından filtrelenmiş bir projeksiyon istiyor:
QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: application/x-www-form-urlencoded
Accept: application/json
select=surname,givenname,email&limit=10
HTTP/1.1 200 OK
Content-Type: application/json
[
{ "surname": "Smith", "givenname": "John", "email": "smith@example.org" },
{ "surname": "Jones", "givenname": "Sally", "email": "sally.jones@example.com" }
]
Spesifikasyondaki en önemli kurallar:
- Her QUERY isteği, gövdesiyle eşleşen bir
Content-Typebaşlığı içermelidir. Başlık eksik olduğunda veya içerikle tutarsız olduğunda sunucu, isteği bir 4xx durumuyla (400, 415 veya 422) reddetmelidir. - Yanıtlar önbelleğe alınabilir. Bunları saklayan bir önbellek, istek gövdesini önbellek anahtarına dahil etmelidir, böylece iki farklı sorgu asla çakışmaz.
- Yönlendirmeler metodu korur: bir 301, 302, 307 veya 308'den sonra istemci, QUERY'yi yeni URI'ye karşı tekrarlar. Yönlendirilen bir POST'u GET'e dönüştüren eski istisna QUERY için geçerli değildir. 303 See Other, sunucunun "sonucu bu Location'dan bir GET ile al" demesinin açık yoludur.
- Bir sunucu, bir kaynağın hangi sorgu biçimlerini anladığını yeni
Accept-Queryyanıt başlığıyla duyurabilir ve desteklendiğinde QUERY, bir OPTIONS yanıtınınAllowbaşlığında görünür. - Tarayıcılarda QUERY, CORS güvenli listesinde yer alan bir metot değildir, bu nedenle çapraz kaynaklı çağrılar bir ön kontrol (preflight) tetikler. sgcWebSockets OpenAPI sunucusunun CORS varsayılanları,
Access-Control-Allow-Methodsiçinde QUERY'yi zaten içeriyor.
HTTP/1.1 istemcisinden QUERY
HTTP/1.1 istemcisi, Post karşılıkları gibi çalışan Query ve QueryAsync metotları kazanıyor: URL'yi ve sorgu gövdesini içeren bir akışı geçirin, istekte Content-Type değerini ayarlayın ve sonucu okuyun.
uses
Classes, sgcHTTP;
var
oClient: TsgcHTTP1Client;
oQuery: TStringStream;
vResult: string;
begin
oClient := TsgcHTTP1Client.Create(nil);
try
oQuery := TStringStream.Create('select=surname,givenname,email&limit=10');
try
oClient.Request.ContentType := 'application/x-www-form-urlencoded';
oClient.Request.Accept := 'application/json';
vResult := oClient.Query('https://api.example.org/contacts', oQuery);
finally
oQuery.Free;
end;
finally
oClient.Free;
end;
end;
QUERY idempotent olduğundan, istemcinin yeniden deneme seçenekleriyle de iyi çalışır: bağlantı hatasıyla başarısız olan bir QUERY, sunucuda bir durum değişikliğini yineleme riski olmadan otomatik olarak yeniden denenebilir. Aynı Query metotları REST API temel istemcisinde de mevcuttur, bu sayede sgcWebSockets üzerine kurulu özel API entegrasyonları bu fiili ekstra bir çalışma olmadan benimseyebilir.
HTTP/2 ve HTTP/3 üzerinden QUERY
HTTP/2 ve HTTP/3 istemcileri aynı fiili sunar. HTTP/2 üzerinden istek, :method sözde başlığı QUERY olarak ayarlanmış şekilde ve gövde DATA çerçeveleri içinde gönderilir:
uses
Classes, sgcHTTP;
var
oClient: TsgcHTTP2Client;
oQuery: TStringStream;
vResult: string;
begin
oClient := TsgcHTTP2Client.Create(nil);
try
oQuery := TStringStream.Create('select=surname,givenname,email&limit=10');
try
vResult := oClient.Query('https://api.example.org/contacts', oQuery);
finally
oQuery.Free;
end;
finally
oClient.Free;
end;
end;
HTTP/3 istemcisi, varsayılan olarak form-urlencoded içerik türünü kullanan bir string aşırı yüklemesi sunar; bu da basit sorguları tek bir çağrıda tutar:
uses
sgcHTTP;
var
oClient: TsgcHTTP3Client;
vResult: string;
begin
oClient := TsgcHTTP3Client.Create(nil);
try
vResult := oClient.Query('https://api.example.org/contacts',
'select=surname,givenname,email&limit=10');
finally
oClient.Free;
end;
end;
Sunucuda QUERY isteklerini işleme
Sunucu tarafında TsgcWebSocketHTTPServer, HTTP/1.1 ve HTTP/2 üzerinden QUERY isteklerini kabul eder ve bunları, istek gövdesi zaten okunmuş ve PostStream içinde hazır olacak şekilde OnCommandOther olayına yönlendirir. Minimal bir işleyici Content-Type başlığını doğrular, sorguyu çalıştırır ve sonucu döndürür:
procedure TForm1.ServerCommandOther(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
vQuery: string;
begin
if SameText(ARequestInfo.Command, 'QUERY') then
begin
// the specification requires a Content-Type on every QUERY request
if (ARequestInfo.ContentType = '') or
not Assigned(ARequestInfo.PostStream) then
begin
AResponseInfo.ResponseNo := 400;
Exit;
end;
ARequestInfo.PostStream.Position := 0;
vQuery := ReadStringFromStream(ARequestInfo.PostStream);
AResponseInfo.ResponseNo := 200;
AResponseInfo.ContentType := 'application/json';
AResponseInfo.ContentText := RunContactsQuery(vQuery);
end;
end;
HTTP/3 sunucusu QUERY gövdelerini aynı şekilde okur, OpenAPI sunucusu bir OpenAPI spesifikasyonunda bildirilen query operasyonlarını yönlendirir ve metodu CORS varsayılanlarında duyurur, HTTP yönlendirme özelliği ise QUERY isteklerini gövdeleriyle birlikte bir arka uç sunucusuna iletir.
Kullanılabilirlik
QUERY desteği, sgcWebSockets 2026.7 içinde HTTP/1.1, HTTP/2 ve HTTP/3 istemcilerini, REST API temel istemcisini, sunucu bileşenlerini ve OpenAPI sunucusunu kapsayacak şekilde, Delphi 7'den Delphi 13'e kadar ve C++ Builder için yer alıyor. Alttaki aktarım biçimi düz HTTP olduğundan, metodu anlayan herhangi bir sunucu veya istemciyle bugün birlikte çalışabilir. En son sürümü sgcWebSockets indirme sayfasından indirebilirsiniz.
Sorularınız, geri bildiriminiz var mı veya geçiş konusunda yardım mı gerekiyor? Bize ulaşın, kodu yazan kişilerden yanıt alacaksınız.
