Ali GÖREN Açık Kaynak, JavaScript, Python, .NET RSS

Hug ile API Oluşturma

Etiketler: programming python api hug

Selam. Bu yazıda size API oluşturmada yardımcı olacak Python kütüphanelerinden birisini tanıtacağım.

Adı Hug. Aslında kendisine framework demek isterdim ama sanırım henüz o potansiyelde değil. Sadece rest isteklerini yapabiliyorsunuz o yanı güzel.

/images/posts/hug.png

Öncelikle Hug asla bir web framework değildir. Bunu bilmek gerekiyor. Yani bu şu anlama geliyor, Hug ile bloglar, forumlar, e ticaret siteleri yazamazsınız. Ancak o sitelere backend desteği sağlayacak API endpointleri oluşturabilirsiniz.

Diğerleri Varken Neden Hug?

Haklı bir soru olabilir. Zira Flask en başta geliyorken bir de üzerine Django rest framework eklenince çok haklı bir şekilde bu soru sorulabilir oluyor.

Diğer yandan Pyramid tabanlı Cornice ve standalone çalışan Falcon ve Pynic framewokleri de örnek verilebilir.

Hug basittir. Basit olması geliştirme aşamasında avantaj sağlıyor olsa bile community kendisi gibi minimalist oluyor. Yani gelişimine katkıda bulunarak kendinizi ayrıca geliştirebilirsiniz.

Öğrenme süresi, diğerlerine göre çok fazla detay gerektirmeyen bu mini tool’u denemediyseniz denemenizi öneririm. Bu yazıda basit bir kaç örneği göreceğiz.

Kurulum

Hug, Python2 desteğine sahip değil sanırım. Python3 desteğine sahip. Kurulumu şöyle yapabiliriz:

pip3 install hug -U

# Eğer python için varsayılan pip, pip3 olarak ayarlanmışsa
pip install hug -U

Nasıl Kullanırım?

Kurulumu başarıyla tamamladıktan sonra bi dosya oluşturalım. Adının çok önemi yok. Bu dosyanın içine import hug şeklinde hug import edilmeli.

Şimdi bu aşamadan sonra iki adet decoratörümüzü çağırmalıyız. Bunlardan ilki local. Ve bir diğeri de istek türünü belirten decoratör. İlk örnekte get metodunu tanımlayan decoratörü çağıracağım:

@hug.get()
@hug.local()
def merhaba(ad: hug.types.text, hug_timer=3):
	return {'ad' : '{0}'.format(ad)}

Bu arada dilerseniz get decoratörüne parametre geçebilirsiniz. Örneğin bu uygulama eğer gerçek bir uygulama gibi çalışıyor olsaydı son kullanıcıya verilere nasıl ulaşacağını gösteren endpointler verebilirdiniz. Gelin örnekleri de şu iki yöntemle verelim:

Tekil kullanım

@hug.get(examples='ad=Ali')
@hug.local()
def merhaba(ad: hug.types.text, hug_timer=3):
	return {'ad' : '{0}'.format(ad)}

Çoğul Kullanım

@hug.get(examples=['ad=Ali', 'soyad=Goren'])
@hug.local()
def merhaba(ad: hug.types.text, hug_timer=3):
	return {'ad' : '{0}'.format(ad)}

Endpointler Metodlardır

Eğer method decoratöre açıkca bir endpoint belirtmediyseniz, varsayılan olarak metod isimleri otomatik olarak endpoint’e dönüşürler. Yukarıdaki metod isminden yola çıkacak olursak http://localhost/merhaba şeklinde bir endpoint görebiliriz.

Ancak dediğim gibi dilersek bu adresleri değiştirebiliriz. Bunun için get decoratörü ilk parametre olarak string türünden endpoint alır.

@hug.get('/naber', examples=['ad=Ali', 'soyad=Goren'])
@hug.local()
def merhaba(ad: hug.types.text, hug_timer=3):
	return {'ad' : '{0}'.format(ad)}

Kısacası metod adı merhaba olsa da endpoint adresimiz .../naber şeklinde değişecektir. Ayrıca parametreler yani queryler beklenen dışında ise error de otomatik olarak veriliyor. Basit olarak endpointler böyle işliyor.

Bir önemli mevzu ise endpointlerin sürümlerinin oluşu. Aynı isme sahip fakat farklı sürümlere sahiplerde çalışan farklı endpointlere şahit olduk çoğu zaman. v1, v2 türünden.

Yine hug bu desteği dahili olarak sunmakta. Bu arada local decoratörüne gerek yok kaldırabilirsiniz. Kendi örneklerinden gittiğim içindi o :).

Versiyon sistemine şöyle örnekler verebiliriz :)

#localhost/v1/naber?ad=Ali
@hug.get('/naber',examples=['ad=Ali'], versions=1)
def merhaba(ad: hug.types.text, hug_timer=3):
	return {'ad' : '{0}'.format(ad)}

# localhost/v2/naber?ad=Ali&soyad=Goren
@hug.get('/naber', examples=['ad=Ali&soyad=Goren'], versions=2)
def merhaba(ad: hug.types.text, soyad: hug.types.text, hug_timer=3):
	return {'ad soyad' : '{0} {1}'.format(ad, soyad)}

En sevdiğim özellik ise versionlara range tanımlanabilmesi. Örneğin sürüm 2 ~ 5 arası tüm api istekleri aynı sonucu döndürsün dersem 2,3,4 endpointleri aynı metoda gidecekler.

@hug.get('/naber', examples=['ad=Ali&soyad=Goren'], versions=range(2, 5))
def merhaba(ad: hug.types.text, soyad: hug.types.text, hug_timer=3):
	return {'ad soyad' : '{0} {1}'.format(ad, soyad)}

Unutmadan dosyanın başına koyacağınız yorum satırı overview yani açıklama için kullanılıyor. Aynı şekilde metod açıklamalarında da usage veriyor. Örnek:

"""Basit bir API endpoint oluşturduk"""
import hug

@hug.get('/naber',examples=['ad=Ali'], versions=1)
def merhaba(ad: hug.types.text, hug_timer=3):
	return {'ad' : '{0}'.format(ad)}

@hug.get('/naber', examples=['ad=Ali&soyad=Goren'], versions=range(2, 5))
def merhaba(ad: hug.types.text, soyad: hug.types.text, hug_timer=3):
	"""Bu metod şunları bunları yapar"""
	return {'ad soyad' : '{0} {1}'.format(ad, soyad)}

Yeri gelmişken metodun aldığı parametrelere dikkat edersek eğer. Python 3.5 ile geldi sanırım tip tanımlama özelliği vardı.

Parametrenin türünün önceden belli olduğu. Aynı işlemi burada da yapabilmektesiniz. Hug içerisinde dahili olarak gelen tiplere sahiptir.

En sonda gelen hug_timer ise tamamen directive özelliği ile alakalıdır.

Deploy

Deploy işlemi bir hayli basit gunicorn ya da uwsgi kullanarak deploy edebilirsiniz:

uwsgi --http 0.0.0.0:8000 --wsgi-file main.py --callable __hug_wsgi__

# ya da gunicorn ile
gunicorn main:__hug_wsgi__

Bu yazıda yaptıklarımu şurada çalıştırmayı denedim. Umarım siz bunu okurken durmamış olur:

https://hugpy-agoren.c9users.io/

Endpointler: [v1, v2, v3, v4]

Sonuç

Bu kısım web tarafında çalışabilecek endpointler ile alakalıydı. Ayrıca @hug.cli() decoratörünü çağırarak komut satırında çalışan uygulamalar da yapabilirsiniz. Bu yazı onu da anlatmaya müsade edecek konumda değil çünkü çok uzadı.

My name is Yoda

Who Am I

24 Level insanım. Bana aşağıdan ulaşabilirsiniz.

Yorumlar