REST URI'sindeki eylemleri (fiiller) temsil etme


16

Müşteri belgelerim için gerçekleştireceğim bir yazdırma işlemim var. Ekleme, güncelleme, silme gibi diğer standart işlemlerin de gerçekleştirilmesi gerekiyor. yani, ben var:

  • Yeni müşteri oluşturmak için:
    URI = / customer / {id}, = POST, Methodname = CreateCustomer ()
  • Güncelleme için:
    URI: / customer / {id}, = PUT, method = UpdateCstomer () yazın
  • Müşteriyi sil:
    URI = / customer / {id} için = DELETE, Methodname = DeleteCustomer () yazın
  • Görünüm için:
    URI: / customer / {id}, = GET, method = GetCustomer () yazın

Şimdi, o müşteri için bir belge yazdırmam gerekirse, bir yazdırma işlevine ihtiyacım var. URI'm şöyle görünebilir: / customer / {id}, type = POST, method = PrintCustomer (). Ancak CreateCustomer için bu URI ve POST türünü kullandım. URI'nin şöyle görünmesini istedim: / customer / Print / {id}, type = POST, method = PrintCustomer ().

Ama URI'mde "Yazdır" fiili olamaz. Bunu yapmanın en iyi yolu nedir? / Customer / document / {id} 'ı URI olarak düşündüm ... ama aynı sorunla karşılaşacağım. "Belge" üzerinde CRUD işlemleri olurdu. Bu yüzden, yine "baskı" için kullandığım şey tükendi. Tavsiye lütfen.


2
Yazdırma genellikle istemci tarafı bir işlemdir, bu yüzden merak ediyorum - kurulumunuz bir REST sunucusuna komut göndermenizi gerektirecek şekilde nasıl?
Shauna

2
@Shauna URI, mutlaka kaynağın yazdırmaya uygun bir sürümü (yani farklı bir görünüm) için sunucuya bir istek olabilir.
Evan Plaice

1
@EvanPlaice - Yeterince adil, ancak yine de yazdırma eylemini istemciye bırakıyor (sunucu tarafı baskı dostu bir sürüm getirildikten sonra bile, hangi aygıtın yazdırılacağına karar verecek ve yazdırma komutunun kendisini gönderecek, komutu bir yazdırma sunucusuna gider). Bir kaynağın baskıya uygun bir sürümünü almak için bir istek mantıksal olarak ... iyi ... GET.
Shauna

@Shauna Bir yazdırma işini tek başına bir HTTP isteğinden tetiklemek tarayıcı güvenliği nedeniyle imkansız olacaktır. Baskıya uygun bir sürüm için istek yalnızca bir GET isteğidir, ancak yine de tarayıcının yazdırılabilir sürümü oluşturması gerektiğini belirtmenin bir yoluna ihtiyacınız vardır. Farklı bir URL belirtebilirsiniz, ancak aslında REST'in ilkelerini ihlal eder, çünkü aslında farklı bir kaynak istemiyorsunuz, sadece aynı kaynağın farklı bir dönüşümü. Dolayısıyla, bir sorgu parametresi ve / veya içerik türü aracılığıyla dönüşümü belirtmenin nedeni.
Evan Plaice

Yanıt olarak göndermek için yeterli temsilcim yok, ancak tyk.io/rest-never-crud'unPOST /customers/123/print geçerli bir şey olduğunu iddia etmesini ilginç buluyorum .
jlh

Yanıtlar:


9

POST"yarat" anlamına gelmez, "süreç" demektir. Mevcut bir kaynağa uygun bir istek göndererek yeni bir kaynak oluşturabilirsiniz (örneğin /customers, yeni bir müşteri oluşturmak için gönder). Ancak POST, düzgün bir CRUD paradigmasına karşılık gelmeyen diğer tüm eylemleri doldurmak için de kullanabilirsiniz .

Yazdırma durumunda, yazdırma işlemini bir kaynağın kendisi olarak düşünmelisiniz. Sistemden sizin için bir "yazdırma işi" yaratmasını istiyorsunuz. Bu, prints/istenen tüm baskılar için kap görevi gören bir kaynağa sahip olabileceğiniz anlamına gelir . Bir şey yazdırmak istediğinizde, POSTbu kaynağa, oluşturmak istediğiniz çıktıyla ilgili tüm bilgileri içeren ve yazdırmak istediğiniz kaynakları bunlarla bağlantılarla tanımlayan bir belgedir.

JSON belgesi olarak şöyle görünebilir:

{
   contents: ["http://site/customers/12345"],
   paper-size: "A4",
   duplex: "true"
}

Açıkçası, bunu yapmak istediğiniz şeyle alakalı olacak şekilde özelleştirmeniz gerekir. Önemli olan, URL'lerini belirterek yazdırılacak diğer kaynakları tanımlamanızdır.

İsteğe yanıt olarak, yalnızca bir 200 OKveya a 204 No-Contentdöndürüp bir ateşle ve unut işlemi olarak değerlendirebilirsiniz. Bunu geliştirmek istiyorsa Ancak, geri dönebilirler 201 Createdörn ve yeni oluşturulan baskı işinin URL belirtin /prints/12345.

Bir kullanıcı daha sonra GETyazdırma işinin durumunu (beklemede, devam ediyor, vb.) Görmek için kaynakta bir gerçekleştirebilir veya a DELETE.

Sorunu kaynak açısından yeniden ifade ettikten sonra, RESTful tasarımı doğal olarak gelmeli ve size hemen düşünmediğiniz şekillerde genişleme ve geliştirme fırsatı vermelidir.


2
POST genellikle oluşturma / ekleme anlamına gelirken put genellikle güncelleme kaydetme / güncelleme anlamına gelir. Genellikle HTML'de kullanılmadığı halde REST'te bu şekilde tanımlanır.
Evan Plaice

2
@EvanPlaice PUT oluşturma / güncelleme fiili olarak PUT isimlerini (daha tanıdık oluşturma + alma + güncelleme yerine bir oluşturma + güncelleme modeli kullanır) ve POST "veri işleme" fiilinin yanı sıra "ekleme" fiili . Blogunda Roy Fielding, POST'u operasyonu standartlaştırmak istemediğinizde kullanılacak fiil olarak tanımladı. POST, bir öğe koleksiyonuna yeni bir öğe eklediğini düşündüğünüzde "oluştur" anlambilimi kullanır. Bu durumda, Tragedya baskı işini işlemek veya eklemek için POST'u kullanarak kafadaki tırnağa çarptı.
Rob

@RobY OK, bu mantıklı. Örnek olarak PUT, veritabanına veri girmek için tasarlanmış bir SPROC'u temsil etmek için kullanılabilir. Oysa bir POST, bu verileri toplamak / hazırlamak için gereken ara adımları ve mutasyonları oluşturabilir. POST işleminin tasarımı, tasarım geliştikçe değişebilir veya değiştirilebilir, ancak PUT işlemleri (ideal olarak) değişmemesi gereken modeli temsil eder. Cevabımı güncelledim ama bu zaten farkı açıklamak için harika bir iş çıkarıyor.
Evan Plaice

4

Bunu daha önce yaptım. Bir belgeyi yazdırmak için yalnızca kaynağın pdf sürümünü döndürürüm. İstemcinin yalnızca Accept header application / pdf ile kaynak için bir GET isteği göndermesi gerekir.

Bu, yazdırma işi gibi geçici kaynak için yeni URI oluşturmayı da önler. HTTP üstbilgisini kullanmak da REST'in bir parçasıdır ve URI'yi temiz tutar.


3

Mevcut URI'nin GET'ine bir parametre eklemeniz yeterlidir

Birden fazla eylem için bir URI kullanmak oldukça tipiktir.

Aynı kaynaktan, ancak farklı bir işlemden bahsediyorsanız, bunu bir parametre olarak tanımlarsınız.

/ Müşteri / {id}? Baskı = true

Daha sonra GET yönteminizi tanımladığınız yerde print parametresinin varlığını algılar ve farklı şekilde ele alırsınız.

REST şu şekilde tanımlanır:

  • POST - Kayıt, varlık veya kaynak oluşturma
  • PUT - Güncelleme, kayıt, varlık veya kaynak
  • SİL - Bir, kayıt, varlık veya kaynağı kaldırma

Öte yandan GET, bir kaynağın alınabileceği birçok farklı form olduğundan, birden çok şekilde kullanılması amaçlanmıştır. Bu nedenle GET istekleri bir sorgu dizesi olarak temsil edilir. Bir veritabanı kaynağıyla çalışıyorsanız, kelimenin tam anlamıyla bir sorgu yoluyla bir görünüm elde edersiniz, ancak REST kasıtlı olarak daha yüksek bir düzeye çıkarılır, çünkü birçok farklı türde kaynakla başa çıkmak için tasarlanmıştır.

REST spesifikasyonu, API'lerin son zamanlarda yoğun bir şekilde kullanmaya başlamasına rağmen oldukça ileriyi düşünüyor.

REST protokolleri hakkında daha fazla bilgi edinmek istiyorsanız " Haters Gonna Hate HATEOAS " ı okumanızı şiddetle tavsiye ederim .


Güncelleme:

@Shauna, akıl yürütmemde ilginç bir delik gösterdi. Hiçbir var gerçek doğru yolu ve birçok biçimi kabul edilebilir olarak kabul edilir. Bunu biraz daha düşündüm ve amaçlanan kullanımınız verileri farklı bir temsile dönüştürmek olduğundan, dönüşümü yeni bir MIME Tipi olarak tanımlamak mantıklıdır.

Örneğin, URI'yi şu şekilde temsil edebilirsiniz:

/customer/{id}+print

Yanıt İçeriği Türünü metne / html + print olarak ayarlayabileceğiniz yer. Bu şekilde gelecekte daha fazla dönüşüm tanımlama seçeneğiniz de olur.

Örneğin:

// for application/json
/customer/{id}+json

// for application/atom+xml
/customer/{id}+atom

Her iki durumda da, tüm formlar kabul edilebilir. Karar verdiğiniz uygulama daha çok kişisel tercihinize ve sunucunuzun yeteneklerine bağlıdır.

Kenara: Açıklığa kavuşturalım çünkü bir karışıklık var gibi görünüyor. Kaynağın nasıl dönüştürüleceğini belirtmek için 'yazdır' sorgu parametresi ve / veya içerik türü kullanılır. Fiziksel bir yazdırma işinin nasıl tetikleneceği değil. Güvenlik nedeniyle, donanım düzeyinde erişim her zaman kullanıcıya / istemciye / tarayıcıya bırakılır.


Eklemek için - Sorgu dizesini ( ?print=true) kullanmaya alternatif olarak URI parametrelerini de kullanabilirsiniz (ie - /customer/{id}/printable). Hangisini kullanacağınız, büyük ölçüde sisteminizin (CMS, çerçeve, genel olarak kod) işlemek için ayarlandığı standarda bağlı olacaktır. Her ikisi de geçerli ve kabul edilebilir sayılır .
Shauna

@Shauna Teknik olarak, en iyi yaklaşım URI '/ customer / {id} + print' ile yazdırmaya özgü bir MIME tipi ve MIME-Type metin / html + print ile yanıt vermektir. Böyle bir yaklaşımın avantajı, aynı URI için birçok MIME türü (örneğin metin / html, metin / x-işaretleme, uygulama / json, vb.) İçin dönüşümler oluşturabilirsiniz. Sunduğunuz çözümün dezavantajı, her farklı MIME Türü için ek bir URI oluşturmanız (ve başka bir rota tanımlamanız) gerekmesidir. REST'i kullanma amacını yener.
Evan Plaice

(devam) URI-saldırılarının öncelikle ROR topluluğu tarafından sunulan bir anti-desen olduğunu iddia ediyorum ama bu onların yararlı olmadıkları anlamına gelmiyor. Daha iyi düşük seviyeli HTTPd sunucularının gelişiyle, REST'i potansiyelinden tam olarak yararlanacak şekilde uygulamak artık daha kolay hale geliyor. Her şey Apache'nin ve her şeyi index.html üzerinden yönlendirmenin yapıldığı günlerden beri çok yol kat etti.
Evan Plaice

2
GET, durum değişiklikleri yapmamalı veya yan etkileri olmamalıdır. GET'in idempotent olduğunu düşünün, yani ara katman yazılımı isteği görmediyse isteği yeniden deneyebilir. Bu durumda, her yeniden deneme belgenin yeni, yeni yazdırılmış bir kopyasıyla sonuçlanır. ;)
Rob

@RobY 'Yazdırma' eyleminin belgeyi tarayıcı ve yazdırma sürücüsü tarafından daha iyi sunulacağı için fiziksel olarak yazdırma işlemini gerçekleştirmeyeceğini varsayıyordum. Bunun yerine, ortam / baskı çıktısı belgenin 'yazdırma dostu' bir temsilini döndürür. Bu nedenle, idempotency korunur. İyi nokta tho, internet üzerinden vatansız bir şekilde baskı işleri göndermek kötü bir zaman olacaktır.
Evan Plaice
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.