OpenAPI ve Spring Boot ile API Dokümantasyonu

İçindekiler
- Giriş
- API Dokümantasyonunun Önemi ve Faydaları
- OpenAPI Nedir?
- Spring Boot ile OpenAPI Entegrasyonu
- API Versiyonlama
- Özelleştirilmiş Dokümantasyon ve API Güvenliği
- Test Otomasyonu
- OpenAPI Alternatifleri ve Karşılaştırması
- En İyi Uygulamalar
- Sonuç
- Kaynakça
Giriş
Uygulama Programlama Arayüzü (Application Programming Interface - API) dokümantasyonu, bir uygulama veya sistemin sunduğu işlevselliklerin, uç noktaların (endpoint), veri yapılarının ve kullanım şekillerinin ayrıntılı olarak tanımlandığı rehberdir. Bu dokümantasyon, geliştiricilere API kullanımını örnek istekler, yanıt formatları, parametre detayları ve olası hata senaryolarıyla kapsamlı bir şekilde açıklar. İyi hazırlanmış bir API dokümantasyonu, geliştiricilerin API ile doğru şekilde entegrasyon kurmasını sağlar, uygulamanın kullanımını hızlandırır ve potansiyel hataları azaltır.
Bu blog yazısında, OpenAPI ve Spring Boot kullanarak API dokümantasyonunun oluşturulması, bu dokümanın bağımsız (standalone) olarak dışa aktarılması, sürüm kontrolü, doküman güvenliğinin sağlanması, test otomasyonu, OpenAPI alternatiflerinin karşılaştırılması ve en iyi uygulama pratikleri ele alınacaktır.
API Dokümantasyonunun Önemi ve Faydaları
İyi bir dokümantasyon, ekip içi ve ekipler arası iş birliğini kolaylaştırır, yeni ekip üyelerinin adaptasyonunu hızlandırır ve öğrenme eğrisini kısaltır. Zaman içinde API’da yapılan değişikliklerin dokümante edilmesi, bakım ve güncellemeleri kolaylaştırarak versiyonlar arası uyumluluğu korur; böylece hangi versiyonda hangi değişikliklerin yapıldığı takip edilebilir ve mevcut kullanıcıların uyum sağlaması kolaylaşır.
API’ın nasıl kullanılacağını net bir şekilde belirlemek yanlış kullanım ihtimalini azaltır. HTTP hata kodları ve açıklamalar gibi detaylar, sorunların daha hızlı belirlenmesini sağlar. Ayrıca iyi bir dokümantasyon, otomatik test senaryoları geliştirilmesini destekler ve mock sunucularla API’ların test edilmesini kolaylaştırır; böylece hizmete geçmeden önce olası senaryolar gözden geçirilebilir.
Anlaşılır ve güncel bir dokümantasyon, kullanıcıların karşılaştıkları sorunları kendi başlarına çözmelerine olanak tanır. Destek ekiplerine olan ihtiyaç azalır ve geliştirici ekiplerin zaman tasarrufu yapmasını sağlar. Sonuç olarak, iyi dokümante edilmiş bir API, sadece ekip içi verimliliği artırmakla kalmaz, aynı zamanda API’ın daha geniş bir kitle tarafından benimsenmesini sağlar. Bu nedenle API geliştirme süreçlerinde detaylı ve kullanıcı dostu bir dokümantasyon hazırlamak, başarılı bir yazılım ekosisteminin temel taşlarından biridir. API dokümantasyonu için çeşitli araçlar vardır; bunlardan en yaygın olan ve bu yazıda değinilecek araç OpenAPI’dır.
OpenAPI Nedir?
OpenAPI, RESTful API’ların nasıl çalıştığını tanımlayan bir spesifikasyon formatıdır ve API’ın uç noktaları, parametreleri, veri modelleri, istek-yanıt formatları gibi tüm teknik detaylarını JSON veya YAML formatında standart hale getirir. Bu sayede, API’ın tasarımından geliştirme, test ve dokümantasyonuna kadar tüm aşamaları tek bir dosya üzerinden yönetilebilir. OpenAPI, API’ın işlevlerini net bir şekilde tanımlayarak ekiplerin aynı kaynaktan çalışmasını sağlar, bu da hataları en aza indirir ve geliştirme sürecini hızlandırır.
Başlangıçta Swagger adıyla tanıtılan bu standart, daha sonra OpenAPI Specification (OAS) olarak genişletildi ve OpenAPI Initiative tarafından yönetilmeye başlandı. Swagger, günümüzde hala Swagger UI ve Swagger Editor gibi araçlarla OpenAPI tanımlarını görselleştiren ve API’ları test etmeyi sağlayan bir araç seti olarak kullanılır. OpenAPI ve Swagger birlikte kullanıldığında yönetimi kolaylaştıran güçlü bir ekosistem sunar. Swagger UI, OpenAPI tanımını kullanarak API’ı kullanıcı dostu bir arayüzde gösterir ve bu arayüzden API çağrıları yapılmasına olanak tanır. OpenAPI’daki temel kavramlar aşağıdaki tabloda sunulmuştur.
Temel Kavramlar
Kavram | Açıklama |
---|---|
Yollar (Paths) | API'ın sunmuş olduğu uç noktaları ve bu uç noktalara yapılacak isteklerin detaylarını tanımlar. |
İşlemler (Operations) | Her bir HTTP metodu (GET, POST, PUT, DELETE) ile yapılan işlemleri ifade eder. |
Parametreler | URL yolunda (base path), sorgu (query) stringinde, başlık (header) veya istek gövdesi (request body) içinde kullanılan verileri tanımlar. |
Bileşenler (Components) | Tekrar kullanılabilir veri yapıları ve şemaları içerir. |
Şemalar (Schemas) | JSON nesnelerinin yapısını ve içerdiği alanları tanımlar. |
Yanıtlar (Responses) | API'ya yapılan isteklerin döndüreceği HTTP durum kodları ve yanıt yapısını belirtir. |
İstek Gövdesi (Request Body) | POST veya PUT işlemlerinde API'ya gönderilen veriyi tanımlar. |
Güvenlik (Security) | API'ın JWT (JSON Web Token), OAuth2 gibi kimlik doğrulama mekanizmalarını içerir. |
Etiketler (Tags) | API uç noktalarını gruplamak ve organize etmek için kullanılır. |
Bilgi (Info) | API'ın genel bilgilerini içerir (başlık, açıklama, sürüm, lisans vb.). |
Sunucular (Servers) | API'ın hangi ortamda (test, prod vb.) çalıştığını belirtir. |
Harici Dokümanlar (ExternalDocs) | API hakkında daha fazla bilgi sunmak için harici bağlantılar sağlar. |
Aşağıdaki OpenAPI örneği, API’ın temel kavramlarını kullanarak basit bir kullanıcı yönetimi sistemi tanımlar. Bu sistem, kullanıcı bilgilerini listelemek ve yeni kullanıcılar eklemek için iki uç içerir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
openapi: 3.0.0
info:
title: Kullanıcı Yönetimi API
description: Kullanıcıların listelenmesi ve eklenmesi için RESTful API.
version: 1.0.0
contact:
name: API Destek Ekibi
email: support@example.com
servers:
- url: 'https://api.prod.com'
description: Üretim Sunucusu
- url: 'https://api.test.com'
description: Test Sunucusu
tags:
- name: Kullanıcı Yönetimi
description: Kullanıcı CRUD işlemleri
paths:
/kullanicilar:
get:
summary: Tüm kullanıcıları getir
tags:
- Kullanıcı Yönetimi
responses:
'200':
description: Başarılı yanıt - Kullanıcı listesi
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Kullanici'
'500':
description: Sunucu hatası
post:
summary: Yeni bir kullanıcı ekler
tags:
- Kullanıcı Yönetimi
requestBody:
description: Eklenecek kullanıcı bilgileri
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Kullanici'
responses:
'201':
description: Kullanıcı başarıyla eklendi
'400':
description: Geçersiz istek
components:
schemas:
Kullanici:
type: object
properties:
id:
type: integer
example: 1
isim:
type: string
example: John Doe
email:
type: string
example: john@example.com
required:
- isim
- email
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- bearerAuth: []
Bu örnekte API’ın 1.0.0 versiyonu, hem üretim hem de test ortamları için yapılandırılmıştır. API’ın tüm uçları JWT tabanlı kimlik doğrulama gerektirmektedir. Bu güvenlik katmanı sayesinde yalnızca yetkili kullanıcılar API’ya erişebilmektedir. İstemciler, isteklerinin Authorization başlığında “Bearer” ön eki ile birlikte geçerli bir JWT göndermek zorundadır. GET /kullanicilar ucu mevcut kullanıcıların listesini JSON formatında döndürür. Başarılı bir istekte (HTTP 200), yanıt gövdesinde kullanıcıların id, isim ve email bilgilerini içeren bir dizi bulunur. Sunucu tarafında bir hata oluşması durumunda HTTP 500 hata kodu döndürülür.
POST /kullanicilar ucu sisteme yeni kullanıcı eklemeyi sağlar. İstek gövdesinde, zorunlu alanlar olan isim ve email bilgileri JSON formatında gönderilmelidir. Kullanıcı başarıyla eklendiğinde HTTP 201 kodu döndürülür. Zorunlu alanların eksik olması gibi durumlarda yani gönderilen veriler geçersizse HTTP 400 hatası alınır.
Swagger UI gibi araçlarda bulunan ‘authorize’ butonu ile JWT tanımlanabilir ve ardından uçlar interaktif olarak test edilebilir. Ayrıca API tanımında kullanılan şemalar ve örnekler sayesinde geliştiriciler isteklerin nasıl yapılandırılması gerektiğini kolayca anlayabilir. Bu API tanımı, geliştiricilerin hızlı bir şekilde entegrasyon yapabilmelerini sağlarken güvenlik ve veri doğrulama gibi önemli konuları da standartlaştırmaktadır.
Bu yaklaşım, API tasarımını koddan bağımsız hale getirir ve API’ın genel bir görünümünü sunar. Öte yandan, anotasyonlar kullanılarak mevcut kod tabanına OpenAPI bilgileri entegre edilebilir. Bu iki yaklaşım arasındaki temel fark, API tanımının nerede ve nasıl yönetildiğidir. YAML tabanlı yaklaşım, API tasarımını önceliklendiren tasarım öncelikli (design-first) metodolojiye uygundur ve API’ın bağımsız bir şekilde tasarlanıp belgelenmesine olanak tanır. Anotasyon tabanlı yaklaşım ise kod öncelikli (code-first) metodolojiye daha uygundur ve mevcut uygulamaya API dokümantasyonunu entegre etmeyi sağlar. Hangi yaklaşımın seçileceği projenin ihtiyaçlarına ve geliştirme sürecine bağlıdır. Yeni bir API tasarlanıyorsa veya API tasarımı kod geliştirmeden önce netleştirmek isteniyorsa YAML tabanlı yaklaşım daha uygun olabilir. Mevcut bir uygulamaya API dokümantasyonu eklemek veya API, kod ile sıkı bir şekilde entegre edilmek isteniyorsa anotasyon tabanlı yaklaşım daha pratik olabilir.
OpenAPI Anotasyonlarının Kullanımı
Anotasyon | Açıklama | Kullanım Örneği |
---|---|---|
@Operation | API ucunun ne yaptığını özetleyen bir açıklama eklemek için kullanılır. | @Operation(summary = "Tüm kullanıcıları getir") |
@Parameter | Yol veya sorgu parametrelerini dokümante eder. | @Parameter(name = "id", description = "Kullanıcı ID") |
@RequestBody | POST veya PUT isteklerinde kullanılan istek gövdesini tanımlar. | @RequestBody(description = "Eklenecek kullanıcı bilgileri") |
@ApiResponse | Belirli bir yanıt durum kodunu ve açıklamasını belirtir. | @ApiResponse(responseCode = "404", description = "Kullanıcı bulunamadı") |
@ApiResponses | Ucun döndüreceği olası yanıtların tanımını yapar. | @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Başarılı") }) |
@Schema | Veri modellerini ve onların yapısını tanımlar. | @Schema(description = "Kullanıcı nesnesi", example = "{ \"id\": 1, \"isim\": \"John\" }") |
@Tag | Uçları belirli bir grupta toplamak için kullanılır. | @Tag(name = "Kullanıcı Yönetimi", description = "Kullanıcı işlemleri") |
@SecurityRequirement | Ucun hangi güvenlik mekanizmalarına ihtiyaç duyduğunu belirtir. | @SecurityRequirement(name = "bearerAuth") |
@Server | API'ın çalıştığı sunucu bilgisini belirtir. | @Server(url = "https://api.prod.com", description = "Üretim sunucusu") |
Bu anotasyonlar, Swagger UI gibi araçlarda API’ın görsel olarak dokümante edilmesini sağlar ve API’ın kullanıcı dostu olmasına katkıda bulunur. Aşağıda bu anotasyonların kullanımını içeren bir örnek verimiştir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/kullanici")
@Tag(name = "Kullanıcı Yönetimi", description = "Kullanıcı işlemleri")
class KullaniciController {
@Operation(summary = "Tüm kullanıcıları getir")
@ApiResponses(
value = [ApiResponse(
responseCode = "200",
description = "Başarılı yanıt"
), ApiResponse(responseCode = "500", description = "Sunucu hatası")]
)
@GetMapping
fun listele(): List<Kullanici> {
return mutableListOf(Kullanici(1, "John Doe", "john@example.com"))
}
@Operation(summary = "Kullanıcı ID'sine göre kullanıcı getir")
@Parameter(name = "id", description = "Kullanıcı ID", required = true)
@ApiResponses(
value = [ApiResponse(
responseCode = "200",
description = "Başarılı yanıt"
), ApiResponse(responseCode = "404", description = "Kullanıcı bulunamadı")]
)
@GetMapping("/{id}")
fun getir(@PathVariable id: Int): Kullanici {
return Kullanici(id, "John Doe", "john@example.com")
}
@Operation(summary = "Yeni bir kullanıcı ekler")
@ApiResponses(
value = [ApiResponse(responseCode = "201", description = "Kullanıcı başarıyla eklendi"), ApiResponse(
responseCode = "400",
description = "Geçersiz istek"
)]
)
@PostMapping
fun ekle(@RequestBody @Schema(description = "Yeni kullanıcı bilgileri") kullanici: Kullanici): Kullanici {
return kullanici
}
data class Kullanici(val id: Int, val name: String, val email: String)
}
Bağımsız Swagger UI Dosyası Nedir ve Neden İhtiyaç Duyulur?
Swagger UI dosyasını bağımsız olarak çıkartmak, API dokümantasyonunu bağımsız bir web sayfası olarak sunma sürecidir. Bu yaklaşım, API’ın OpenAPI spesifikasyonunu kullanarak HTML, CSS ve JavaScript dosyalarından oluşan ayrı bir dokümantasyon arayüzünü oluşturmayı içerir. Bu sayede API geliştiricileri, dokümantasyonu API projesinden ayırarak hem çevrim içi hem de çevrim dışı ortamlarda kullanılabilir hale getirebilir.
Bu yöntem, özellikle mikroservis mimarilerinde büyük avantaj sağlar. Her bir servisin API dokümantasyonu ayrı ayrı yönetilebilir ve dağıtılabilirken dokümantasyonun belirli bir sürümü API’ın kendisiyle birlikte versiyon kontrol sisteminde saklanabilir. Bu yaklaşım, API’ın gelişim sürecini takip etmeyi ve eski sürümlere erişimi kolaylaştırır.
Bağımsız dokümantasyon yaklaşımı, güvenlik açısından da önemli avantajlar sunar. Hassas bilgiler içeren API’lar için dokümantasyon, yetkilendirme mekanizmalarıyla korunabilir ve sadece izin verilen kullanıcılara sunulabilir. Ayrıca Swagger UI’nın özelleştirilebilir yapısı sayesinde dokümantasyon kurumsal kimliğe uygun hale getirilebilir ve kullanıcı deneyimi iyileştirilebilir.
Bu yöntem, daha az bağımlılık ve hızlı dağıtım avantajlarıyla API geliştirme sürecini basitleştirirken dokümantasyonu daha esnek ve erişilebilir hale getirir. Özellikle farklı ekipler veya dış kullanıcılarla entegrasyon sürecinde API’ı çalıştırmadan veya projeye erişmeden dokümantasyonun incelenebilmesi, iş birliğini ve geliştirme sürecini önemli ölçüde hızlandırır.
OpenAPI ve Spring Boot entegrasyonunu, bağımsız dosya çıkartmayı aşağıdaki demo üzerinden inceleyelim.
Spring Boot ile OpenAPI Entegrasyonu
1. Bağımlılık Eklenmesi
Maven için:
pom.xml
1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
Gradle için:
build.gradle
1
2
3
dependencies {
implementation ("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0")
}
2. Örnek Bir REST API Oluşturma ve OpenAPI Anotasyonlarıyla API’yı Dokümante Etme
1
2
3
4
5
data class Musteri(
val id: Long,
val isim: String,
val email: String
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/api/v1/musteriler")
@Tag(name = "Musteri", description = "Müşteri Yönetim API")
class MusteriController {
private val musteriler = mutableListOf(
Musteri(1, "John Doe", "john@example.com"),
Musteri(2, "Jane Smith", "jane@example.com")
)
@Operation(summary = "Tüm müşterileri getir", description = "Tüm müşterilerin listesini getirir")
@ApiResponses(value = [
ApiResponse(responseCode = "200", description = "Başarılı işlem"),
ApiResponse(responseCode = "404", description = "Müşteriler bulunamadı")
])
@GetMapping
fun listele(): ResponseEntity<List<Musteri>> {
return if (musteriler.isNotEmpty()) {
ResponseEntity.ok(musteriler)
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).body(emptyList())
}
}
@Operation(summary = "Yeni bir müşteri ekle", description = "Listeye yeni bir müşteri ekler")
@ApiResponses(value = [
ApiResponse(responseCode = "201", description = "Müşteri oluşturuldu"),
ApiResponse(responseCode = "400", description = "Geçersiz giriş")
])
@PostMapping
fun ekle(@RequestBody musteri: Musteri): ResponseEntity<Musteri> {
musteriler.add(musteri)
return ResponseEntity.status(HttpStatus.CREATED).body(musteri)
}
@Operation(summary = "ID ile müşteri getir", description = "Belirtilen ID'ye göre bir müşteriyi getirir")
@ApiResponses(value = [
ApiResponse(responseCode = "200", description = "Müşteri başarıyla getirildi"),
ApiResponse(responseCode = "404", description = "Müşteri bulunamadı")
])
@GetMapping("/{id}")
fun getir(@PathVariable id: Long): ResponseEntity<Musteri> {
val musteri = musteriler.find { it.id == id }
return if (musteri != null) {
ResponseEntity.ok(musteri)
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).build()
}
}
}
3. Swagger UI’yı Görüntüleme ve Yapılandırma
Varsayılan olarak Swagger UI’na http://localhost:8080/swagger-ui/index.html adresinden erişilebilir ancak adresi yapılandırmak gerekirse application.properties dosyasında belirtilebilir:
1
springdoc.swagger-ui.path=/dokuman.html
Bu adımların sonunda Spring Boot ve OpenAPI kullanılarak API dokümanı elde edilir. Swagger UI üzerinden görselleştirilebilen bir REST API projesi oluşur.

4. Oluşan Swagger UI’yı Bağımsız Olarak Çıkartma
Geliştirme ortamında proje çalıştıktan sonra erişilen bu dosyayı projeden bağımsız olarak çıkartmak için şu adımlar izlenir:
Gradle için openapi-gradle-plugin’i eklenir.
build.gradle
1
2
3
plugins {
id("org.springdoc.openapi-gradle-plugin") version "1.8.0"
}
Maven için exec-maven-plugin‘i eklenir.
pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>generate-openapi-json</id>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>curl</executable>
<arguments>
<!-- OpenAPI JSON dokümanını almak için API URL'i -->
<argument>http://localhost:8080/v3/api-docs</argument>
<!-- JSON dokümanını build dizinine kaydetme işlemi -->
<argument>-o</argument>
<argument>${project.build.directory}/openapi.json</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
OpenAPI dokümanlarını oluşturma ve API dokümanlarına erişimi sağlama sürecini özelleştirmek için apiDocsUrl ayarı geçerek Spring Boot uygulamasının çalıştırdığı API’ların OpenAPI formatındaki JSON dokümantasyonuna hangi URL’den erişeceği belirtilir. waitTimeInSeconds ise bu dokümantasyonun oluşturulması sırasında API’ın yanıt vermesi için ne kadar beklenmesi gerektiğini ayarlar.
build.gradle
1
2
3
4
openApi {
waitTimeInSeconds = 90
apiDocsUrl = "http://localhost:8080/v3/api-docs"
}
Gerekli ayarları geçtikten sonra yansımaları için gradle/maven reload yapılır.
Dokümanın oluşması için çalıştırılması gereken komutlar:
Gradle için:
1
./gradlew generateOpenApiDoc
Maven için:
1
mvn exec:exec@'generate-openapi-json'
Maven’da target klasörü altında, Gradle’da ise build klasörü altında oluşan openapi.json dosyası, Swagger UI’nda görüntülenen dokümanın JSON formatındaki halidir.

Oluşan bu json dosyasını html olarak çıkartmak için ufak bir Python scripti gerekmektedir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import yaml, json, sys
TEMPLATE = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.24.2/swagger-ui.css" >
<style>
html {
box-sizing: border-box;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.24.2/swagger-ui-bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.24.2/swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function() {
var spec = %s;
const ui = SwaggerUIBundle({
spec: spec,
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
window.ui = ui
}
</script>
</body>
</html>
"""
if __name__ == '__main__':
try:
spec = yaml.safe_load(sys.stdin)
sys.stdout.write(TEMPLATE % json.dumps(spec))
except yaml.YAMLError as error:
sys.stderr.write('Error parsing YAML!\n')
sys.exit(1)
Bu scripti çalıştırmak için gereken komut:
1
python src/main/kotlin/com/openapi/demo/json-to-html.py < build/openapi.json > src/main/resources/static/api-documentation.html
Belirtilen dizinde api-documentation.html dosyası oluşur. Artık bu API dokümanına projeden bağımsız bir şekilde erişilebilir.
Docker üzerinde çalışan bir proje için komutları manuel olarak çalıştırmak yerine Python, Docker’a kurulup gerekli komutlar oraya da geçilebilir.
1
2
3
4
5
6
7
8
9
10
11
FROM python:3.8-alpine
WORKDIR /app
RUN pip install PyYAML
COPY ./apps/demo /app
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
entrypoint.sh
1
2
cd /app
python src/main/kotlin/com/openapi/demo/json-to-html.py < build/openapi.json > src/main/resources/static/api-documentation.html
Bu komut Docker’da kurulan Python içerisinde çalışıp bittikten sonra Python durdurulur ve dosya, Python konteyner içerisinde oluşur.
API Versiyonlama
API versiyonlama, bir API’ın değişimini yönetmek için kullanılan kritik bir tekniktir. Bu yaklaşım, geliştiricilere mevcut kullanıcıları etkilemeden API’yı geliştirme, yeni özellikler ekleme ve bakım yapma imkânı sunar. Versiyonlama sayesinde farklı kullanıcı ihtiyaçlarına cevap veren çeşitli API sürümleri sunulabilir ve büyük değişiklikler kontrollü bir şekilde uygulanabilir. Geriye dönük uyumluluğu koruyarak eski sürümlerin desteklenmesine olanak tanır ve kullanıcılara yeni sürümlere geçiş için zaman verir. Bu, özellikle mikroservis mimarilerinde ve büyüyen API tabanlı projelerde esneklik ve sürdürülebilirlik sağlar. Etkili bir API versiyonlama stratejisi, anlamlı versiyon numaralandırması, detaylı dokümantasyon, eski sürümlerin kullanımının izlenmesi ve zamanla kullanımdan kaldırılması gibi unsurları içerir. Bu yaklaşım, API’ların uzun vadeli başarısını desteklerken geliştiriciler ve kullanıcılar arasında güven oluşturur ve API ekosisteminin sağlıklı bir şekilde büyümesine katkıda bulunur.
OpenAPI ile Versiyonlama
OpenAPI’da versiyonlama, hem info alanında gösterilebilir hem de API uçlarına veya başlıklarına entegre edilebilir. En yaygın yöntem, URL veya başlık tabanlı versiyonlamadır. Seçim, API’ın kullanım senaryolarına ve kullanıcıların beklentilerine göre yapılır.
1. info Bölümünde Versiyon Belirtme
OpenAPI dokümanının başında, API’ın genel bilgilerini içeren info alanında versiyon belirtilebilir.
1
2
3
4
openapi: 3.0.3
info:
title: Kullanıcı Yönetimi API
version: 1.0.0
info.version alanı, API’ın mevcut sürümünü belirtir ve genellikle SemVer (Semantik Versiyonlama) formatında kullanılır. SemVer, sürümü üç bölümde ifade eder: major (ana sürüm), geriye dönük uyumsuz büyük değişiklikleri içerir (örneğin 2.0.0); minor (alt sürüm), yeni özellikler ekleyip uyumluluğu koruyan güncellemeleri gösterir (örneğin 1.1.0); patch (yama sürümü) ise küçük hata düzeltmelerini veya iyileştirmeleri temsil eder (örneğin 1.0.1). Bu yapı, kullanıcıların değişikliklerin boyutunu ve etkisini kolayca anlamalarını sağlar; minor ve patch sürümleri sorunsuz geçişlere olanak tanır.
2. URL Üzerinden Versiyonlama
Her API sürümü için farklı bir URL yolu tanımlanabilir. Bu yöntemde her API sürümünün ayrı bir ucu olur (/v1, /v2).
1
2
3
4
5
6
7
8
paths:
/v1/kullanicilar:
get:
summary: Kullanıcı listesini getirir
/v2/kullanicilar:
get:
summary: Kullanıcı listesini ek bilgilerle getirir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
@RequestMapping("/api/v1/kullanicilar")
class KullaniciControllerV1 {
@GetMapping
fun listeleV1(): List<Kullanici> {
return kullaniciServis.listele()
}
}
@RestController
@RequestMapping("/api/v2/kullanicilar")
class KullaniciControllerV2 {
@GetMapping
fun listeleV2(): List<Kullanici> {
return kullaniciServis.ekstraBilgilerleListele()
}
}
3. Başlık Üzerinden Versiyonlama
Parameters altında başlık tanımlanır. API-Versiyon adlı başlık ile istenen API sürümü seçilir.
1
2
3
4
5
6
7
8
9
10
11
paths:
/kullanicilar:
get:
summary: Kullanıcı listesini getirir
parameters:
- in: header
name: API-Versiyon
schema:
type: string
required: true
example: v1
1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequestMapping("/api/kullanicilar")
class KullaniciController {
@GetMapping
fun listele(@RequestHeader(value = "API-Versiyon") version: String): List<Kullanici> {
return if (version == "v1") {
kullaniciService.listele()
} else {
kullaniciService.ekstraBilgilerleListele()
}
}
}
4. Sorgu Parametresi ile Versiyonlama
Sorgu parametreleri ile versiyon belirtmek için parameters kısmında sorgu parametresi tanımlanır. Kullanıcılar, API’ya ?version=v1 gibi bir sorgu ile istedikleri versiyon için istek atar.
1
2
3
4
5
6
7
8
9
10
11
paths:
/kullanicilar:
get:
summary: Kullanıcı listesini getirir
parameters:
- in: query
name: version
schema:
type: string
required: true
example: v1
1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@RequestMapping("/api/kullanicilar")
class KullaniciController {
@GetMapping
fun listele(@RequestParam(value = "version", required = true) version: String): List<Kullanici> {
return if (version == "v2") {
kullaniciService.ekstraBilgilerleListele()
} else {
kullaniciService.listele()
}
}
}
5. İçerik Uzlaşımı (Content Negotiation) ile Versiyonlama
Accept başlığı ile versiyonlamadır. Accept başlığı, isteklerin hangi sürümle çalışacağını belirler.
1
2
3
4
5
6
7
8
9
10
11
paths:
/users:
get:
summary: Kullanıcı listesini getirir
parameters:
- in: header
name: Accept
schema:
type: string
required: true
example: application/vnd.api.v1+json
1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@RequestMapping("/api/kullanicilar")
class KullaniciController {
@GetMapping
fun listele(@RequestHeader(value = "Accept", required = true) acceptHeader: String): List<Kullanici> {
return if (acceptHeader == "application/vnd.api.v2+json") {
kullaniciService.ekstraBilgilerleListele()
} else {
kullaniciService.listele()
}
}
}
Özelleştirilmiş Dokümantasyon ve API Güvenliği
OpenAPI, API’ların yapısını tanımlarken metadata ekleme, veri modelleri oluşturma ve güvenlik yapılandırmaları gibi özellikler sunar. Metadata sayesinde API hakkında bilgi (başlık, açıklama, sürüm vb.) sağlanır. Özel şema (custom schema) tanımlamaları, API’ın veri modellerini standart hale getirerek JSON veya diğer formatlarda nasıl görüneceklerini belirler. API güvenliği için JWT veya OAuth2 gibi mekanizmalar tanımlanarak kimlik doğrulama ve yetkilendirme süreçleri yönetilir. Bu yapı, kullanıcıların API’yı anlamasını kolaylaştırırken güvenli ve sürdürülebilir bir geliştirme süreci sunar.
JWT Entegrasyonu:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
openapi: 3.0.0
info:
title: API Güvenlik Servisi
version: 1.0.0
description: API dokümantasyonu ve güvenlik özellikleri
servers:
- url: http://localhost:8080
paths:
/guvenli-veri:
get:
tags: ['Güvenli İşlemler']
summary: Güvenli veri getirme
security:
- apiKeyAuth: []
- bearerAuth: []
parameters:
- in: header
name: Request-ID
required: true
schema:
type: string
example: "123e4567-e89b-12d3-a456-426614174000"
responses:
'200':
description: Başarılı yanıt
content:
application/json:
schema:
type: object
properties:
message:
type: string
data:
type: object
example:
message: "Veri başarıyla getirildi"
data: {
id: 1,
name: "Test Verisi"
}
'401':
$ref: '#/components/responses/UnauthorizedError'
'429':
$ref: '#/components/responses/TooManyRequests'
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: X-API-Key
bearerAuth:
type: http
scheme: bearer
responses:
UnauthorizedError:
description: Yetkisiz erişim
TooManyRequests:
description: İstek limiti aşıldı
Bu YAML dosyası güvenlik açısından önemli özellikler içermektedir. Tanımlanan API, çift katmanlı bir kimlik doğrulama sistemi kullanmaktadır, bunlar API Key Authentication ve Bearer Token Authentication‘dır. API Key, başlıkta ‘X-API-Key’ parametresi ile gönderilen özel bir anahtarken; Bearer Token, JWT gibi bir token kullanarak yetkilendirme sağlar. Bu iki katmanlı yaklaşım, yetkisiz erişimlere karşı güçlü bir koruma sağlar. Ayrıca her API isteği için zorunlu tutulan benzersiz Request-ID parametresi, güvenlik olaylarının ve potansiyel saldırıların izlenmesini kolaylaştırır. Bu yaklaşım ile hem API Key hem de Bearer Token kullanarak güvenliği sağlayan, zorunlu bir Request-ID başlığı gerektiren ve başarılı durumda JSON formatında veri döndüren bir API tanımlanmış olur. Aynı zamanda bu tanım, yetkisiz erişim (401) ve istek limitinin aşılması (429) gibi hata durumlarını da içerir.
OAuth2 Entegrasyonu:
JWT yerine OAuth2 entegrasyonu yapılabilir:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: header
name: X-API-Key
OAuth2Security:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth-server.com/oauth/authorize
tokenUrl: https://auth-server.com/oauth/token
refreshUrl: https://auth-server.com/oauth/refresh
scopes:
read: Veri okuma izni
write: Veri yazma izni
admin: Yönetici izinleri
clientCredentials:
tokenUrl: https://auth-server.com/oauth/token
scopes:
read: Veri okuma izni
write: Veri yazma izni
Bu yapı, OAuth2 protokolü ile çalışır ve authorizationCode akışını kullanarak yetkilendirme sağlar. scopes bölümü, API’ın hangi izinlere ihtiyaç duyduğunu belirtir.
Test Otomasyonu
OpenAPI test otomasyonu, API’ın tanım dosyasına dayanarak otomatik testlerin yürütülmesini sağlar ve API’ın dokümantasyonuyla gerçek davranışının tutarlı olmasını garanti eder. Bu süreç, uçların beklenen yanıtları döndüğünü, veri modellerinin doğru çalıştığını ve performans sınırlarının içinde kaldığını kontrol eder. Test otomasyonu, regresyon testleriyle eski işlevlerin güncellemelerden etkilenmediğini doğrular. Sürekli entegrasyon (CI) ve sürekli teslimat (CD) süreçlerine entegre edilerek her kod değişikliğinde otomatik olarak çalıştırılabilir, hızlı hata tespiti sağlarken geliştirme sürecinin kalitesini ve verimliliğini artırır. Postman, RestAssured, Dredd ve Swagger Codegen gibi araçlarla yapılabilen bu testler, API tanımına uygun iskelet test senaryolarını otomatik olarak oluşturur. Bu iskelet testler, her uç için temel API çağrılarını içerir; ancak gerçek kullanım senaryolarını kapsayabilmesi için geliştirici tarafından genişletilmesi ve ek doğrulamalar eklenmesi gerekir. Swagger Codegen ile tanımların bulunduğu openapi.yaml dosyasından otomatik test senaryosu oluşturmak için bu komut çalıştırılabilir:
1
2
3
4
5
6
swagger-codegen generate \
-i path/openapi.yaml \
-l java \
-o output_folder \
--api-package com.openapi.demo \
--additional-properties=library=resttemplate
OpenAPI Alternatifleri ve Karşılaştırması
API’lar için farklı tanımlama standartları, kullanım alanlarına ve ihtiyaçlara göre çeşitli avantajlar sunar.
Özellik | OpenAPI | GraphQL | gRPC | RAML | API Blueprint |
---|---|---|---|---|---|
Mimari | RESTful API | Sorgu Dili | Uzak Prosedür Çağrısı (Remote Procedure Call - RPC) | RESTful API | RESTful API |
Kapsam ve Yaygınlık | Çok yaygın | Yaygın | Mikroservislerde yaygın | Kurumsal projelerde yaygın | Küçük projelerde yaygın |
Esneklik | REST kurallarına bağlı | Dinamik ve esnek sorgular | Strikt, kontrat tabanlı | REST kurallarına bağlı | Sade ve anlaşılır yapıda |
Verimlilik | Orta (JSON/HTTP) | Optimize sorgular | Yüksek (Protobuf, HTTP/2) | Orta (JSON/HTTP) | Orta (JSON/HTTP) |
Performans | Orta | Yüksek | Yüksek | Orta | Orta |
Dokümantasyon Araçları | Swagger, Redoc | Apollo Studio, GraphQL | Protoc-gen-doc | Anlaşılır YAML yapısı | Markdown benzeri doküman |
Kullanım Alanları | Genel amaçlı API'lar | İstemciye özel veri ihtiyaçları | Mikroservisler, IoT, Mobil Uygulamalar | Kurumsal projeler | Basit ve küçük projeler |
Avantajlar | Geniş ekosistem, Standart olmuş, Araç desteği çok, REST API'lar için ideal | Esnek veri sorgulama, Güçlü tip sistemi, Tek uç nokta | Yüksek performans, İki yönlü akış (streaming), Güçlü tip kontrolü, Otomatik kod üretimi | Kurumsal (Enterprise) odaklı, Detaylı özellikler, İyi dokümantasyon, API modellemede güçlü | Öğrenmesi kolay, Hızlı prototipleme, İyi okunabilirlik |
Dezavantajlar | Karmaşık olabilir, YAML söz dizimi (syntax) hataya açık | Özel altyapı gerekli, Cache yönetimi zor, Kompleks sorgular | HTTP/2 gerekli, Öğrenmesi zor, Browser desteği sınırlı | Topluluk küçük, Araç desteği sınırlı | Kurumsal için yetersiz, Sınırlı özellikler |
Topluluk Büyüklüğü | Çok Büyük | Büyük | Büyük | Orta | Küçük |
En iyi Olduğu Durumlar | Public REST API'lar, Kurumsal sistemler, API öncelikli geliştirme | Mobile uygulamalar, Karmaşık veri ilişkileri, Gerçek zamanlı güncellemeler | Mikroservisler, Düşük gecikme süresi (latency) gereken sistemler, Veri akışı (streaming data) | Büyük kurumsal projeler, Kompleks API'lar, Detaylı dokümantasyon | API prototipler, Küçük projeler, Hızlı geliştirme |
Her API standardı, farklı kullanım senaryolarına uygun avantajlar sunar ve seçim, projenin ihtiyaçlarına göre yapılmalıdır. OpenAPI, geniş araç desteği ve yaygın kullanımıyla RESTful API’ler için en ideal seçenek olurken GraphQL esnek sorgulama yapısıyla özellikle istemcinin özelleştirilmiş veri ihtiyaçlarını karşılayan projelerde öne çıkar. gRPC, düşük gecikme süresi ve yüksek performans gerektiren mikroservis mimarilerinde tercih edilirken tarayıcı desteği eksikliği nedeniyle ön yüz projeleri için uygun değildir. RAML, okunabilirlik ve yeniden kullanılabilirlik avantajlarıyla kurumsal projelerde güçlü bir alternatif sunarken API Blueprint küçük projeler ve hızlı prototipleme süreçleri için pratik bir çözümdür. Doğru seçim için API’ın yapısı, kullanım alanı, performans gereksinimleri ve geliştirme ekibinin deneyimi gibi faktörler değerlendirilmelidir.
En İyi Uygulamalar
OpenAPI ile API tasarımında en iyi uygulamalara dikkat etmek; kullanıcı dostu, güvenli ve performanslı API’ların geliştirilmesini sağlar. Tutarlı uç isimlendirmesi, doğru HTTP durum kodları, versiyonlama, güvenlik önlemleri ve iyi dokümantasyon gibi unsurlar, API’ın sürdürülebilirliğini artırır. Ayrıca şema tanımlamaları ve performans optimizasyonları, API’ın kullanımını kolaylaştırır ve genişletilebilirliğini sağlar. Bu uygulamalarla, OpenAPI tabanlı projelerde yaygın hatalardan kaçınılabilir ve kaliteli API’lar sunulabilir.
1. Anlaşılır ve Tutarlı Uç İsimlendirmesi
- Uygulama: Kaynak tabanlı, tutarlı ve anlamlı uçlar (ör. /kullanicilar, /siparisler) tanımlanmalıdır.
- Kaçınılması Gereken Hata: Uçlarda fiil kullanımı (ör. /kullanicilariGetir, /siparisOlustur) gibi yanlış uygulamalardan kaçınılmalıdır.
- OpenAPI Desteği: OpenAPI tanımlamalarında uçları organize ederek her kaynağa uygun HTTP metotları tanımlanabilir. Aşağıdaki yaml ve anotasyon örneklerinde, uçların nasıl organize edileceği gösterilmiştir.
1
2
3
paths:
/kullanicilar:
get:
1
2
@GetMapping("/kullanicilar")
fun listele(): List<Kullanici> { }
2. Doğru HTTP Durum Kodları ve Anlamlı Hata Mesajları Kullanma
- Uygulama: Başarı ve hata durumlarında uygun HTTP durum kodları (ör. 200 OK, 201 Created, 400 Bad Request, 404 Not Found) ve açıklayıcı hata mesajları sağlanmalıdır. Yanıtlar, hatanın nedenini ve çözüm yolunu net bir şekilde açıklamalıdır.
- Kaçınılması Gereken Hata: Yanlış veya yetersiz durum kodlarının ve belirsiz hata mesajlarının kullanımı, API kullanıcılarının sorunları çözmesini zorlaştırır. Örneğin, her hata durumunda “500 Internal Server Error” kullanmak yerine daha spesifik durum kodları döndürmek gerekir.
- OpenAPI Desteği: Her uç için durum kodları ve hata mesajları dokümante edilebilir. Aşağıdaki yaml ve anotasyon örneklerinde, hata kodlarının nasıl tanımlanacağı gösterilmiştir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
paths:
/kullanicilar:
get:
responses:
'200':
description: "Başarılı istek"
'400':
description: "Geçersiz istek"
content:
application/json:
example:
error: "Geçersiz parametre"
'404':
description: "Kaynak bulunamadı"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@ApiResponses(value = [
ApiResponse(
responseCode = "200",
description = "Başarılı istek",
content = [Content(schema = Schema(implementation = Kullanici::class))]
),
ApiResponse(
responseCode = "400",
description = "Geçersiz istek",
content = [Content(schema = Schema(implementation = HataYaniti::class))]
),
ApiResponse(
responseCode = "404",
description = "Kaynak bulunamadı",
content = [Content(schema = Schema(implementation = HataYaniti::class))]
)
])
@GetMapping("/kullanicilar")
fun listele(): List<Kullanici> { }
3. Versiyonlama ile Geriye Dönük Uyumluluğu Sağlama
- Uygulama: Büyük değişikliklerde API versiyonlama yaparak geriye dönük uyumluluk korunmalıdır. (Ör. /v1/kullanici).
- Kaçınılması Gereken Hata: Versiyonlama yapmadan değişiklik yapmak, mevcut kullanıcıların uygulamalarını bozabilir.
- OpenAPI Desteği: servers veya paths altında versiyon numarası ekleyerek yönetilebilir. Aşağıdaki yaml ve anotasyon örneklerinde, versiyonlamanın nasıl yapılacağı gösterilmiştir.
1
2
servers:
- url: https://api.demo.com/v1
1
2
3
@RestController
@RequestMapping("/api/v1")
class ApiV1Controller { }
4. Anlamlı Dokümantasyon Sağlama
- Uygulama: API’ın nasıl kullanılacağını anlatan detaylı açıklamalar ve örnekler eklenmelidir.
- Kaçınılması Gereken Hata: Eksik veya belirsiz dokümantasyon, kullanıcıların entegrasyonunu zorlaştırır.
- OpenAPI Desteği: summary ve description alanlarıyla uç noktaların açıklamaları yapılabilir; schema ile sınıf ve değişkenlerin açıklamaları ve örnek değerleri sunulabilir. Aşağıdaki yaml ve anotasyon örneklerinde, uç noktalara nasıl açıklama ekleneceği gösterilmiştir.
1
2
3
4
5
paths:
/kullanicilar:
get:
summary: "Kullanıcıları listeler"
description: "Tüm kayıtlı kullanıcıları listeler."
1
2
3
@Operation(summary = "Kullanıcıları listeler", description = "Tüm kayıtlı kullanıcıları listeler.")
@GetMapping("/kullanicilar")
fun listele(): List<Kullanici> { }
5. API Güvenliğini Sağlama
- Uygulama: Kimlik doğrulama ve yetkilendirme için JWT veya OAuth2 kullanılmalı ve tüm veriler HTTPS üzerinden iletilmelidir.
- Kaçınılması Gereken Hata: Güvenlik olmadan API’yı açık bırakmak büyük bir risktir.
- OpenAPI Desteği: SecurityScheme ile kimlik doğrulama mekanizmaları tanımlanabilir. Aşağıdaki yaml ve anotasyon örneklerinde, kimlik doğrulamanın nasıl gerçekleşeceği gösterilmiştir.
1
2
3
4
5
6
7
8
9
components:
securitySchemes:
jwtAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- jwtAuth: []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@SecurityScheme(
name = "bearer-key",
type = SecuritySchemeType.HTTP,
scheme = "bearer",
bearerFormat = "JWT",
description = "JWT authentication"
)
@RestController
@SecurityRequirement(name = "bearer-key")
@Tag(name = "Güvenli Uçlar")
class GuvenliController {
@Operation(
summary = "Güvenli işlem",
security = [SecurityRequirement(name = "bearer-key")]
)
@GetMapping("/guvenli-uc")
fun guvenliIslem(): String { }
}
6. Özel Şema ve Örnek Tanımlama
- Uygulama: Veri modelleri için özel şemalar tanımlanmalı ve JSON örnekleri eklenmelidir.
- Kaçınılması Gereken Hata: Karmaşık veri yapıları için açık şema tanımlamamak entegrasyonu zorlaştırır.
- OpenAPI Desteği: Schema ile veri modelleri tanımlanabilir. Aşağıdaki yaml ve anotasyon örneklerinde, schema ile veri modellerinin nasıl tanımlanacağı gösterilmiştir.
1
2
3
4
5
6
7
8
9
10
11
components:
schemas:
User:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: "John Doe"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Schema(description = "Kullanıcı detaylı bilgileri")
data class KullaniciDetay(
@field:Schema(
description = "Kullanıcı ID",
example = "1",
type = "integer"
)
val id: Long,
@field:Schema(
description = "Kullanıcı İsim ve Soyismi",
example = "John Doe",
type = "string"
)
val isim: String
)
7. Performans ve Ölçeklenebilirlik için Optimizasyon
- Uygulama: Sayfalama (pagination) ve filtreleme desteği eklenmelidir. Gereksiz veri transferi önlenmelidir.
- Kaçınılması Gereken Hata: Tüm veriyi tek seferde döndürmek API performansını düşürür.
- OpenAPI Desteği: Parameter ile sayfalama ve filtreleme sağlanabilir. Aşağıdaki yaml ve anotasyon örneklerinde, parameter ile sayfalamanın nasıl yapılacağı gösterilmiştir.
1
2
3
4
5
6
7
8
parameters:
- name: page
in: query
description: "Sayfa numarası"
required: false
schema:
type: integer
example: 1
1
2
3
4
5
6
7
8
9
10
11
@GetMapping("/kullanicilar")
fun sayfalandirilmisKullanicilariGetir(
@Parameter(
name = "page",
`in` = ParameterIn.QUERY,
description = "Sayfa numarası",
required = false,
schema = Schema(type = "integer", example = "1")
)
@RequestParam(value = "page", required = false) page: Int?
): Page<Kullanici> {}
Sonuç
OpenAPI ve Spring Boot’un entegre kullanımı, modern API geliştirme süreçlerinde belgelendirme, güvenlik, sürüm yönetimi ve test otomasyonunu standartlaştırarak projelere büyük avantajlar sağlar. Bu yazıda, API dokümantasyonunun proje ekiplerine sağladığı faydalar ele alınmış; OpenAPI Specification ile API tanımlamanın geliştiricilere sağladığı esneklik ve uyumluluk detaylandırılmıştır. OpenAPI’ın sağladığı standartlaştırılmış yapı sayesinde API uçlarının ve veri modellerinin nasıl dokümante edilmesi gerektiği incelenmiştir. Ayrıca bağımsız bir HTML dokümantasyon çıktısının alınmasıyla hem teknik hem de teknik olmayan paydaşlar için anlaşılır ve kolay erişilebilir bir bilgi kaynağı sağlanmıştır.
Tüm bu detaylar göz önüne alındığında OpenAPI ve Spring Boot’un birlikte kullanımı, projelere esneklik ve uzun vadede bakım kolaylığı kazandıran güçlü bir çözüm sunar. API geliştirme, versiyonlama ve bakım süreçlerinde güvenilir ve kapsamlı bir yapı arayan ekipler için bu iki aracın entegrasyonu önemli bir değer sağlar.
Kaynakça
- https://swagger.io/specification/
- https://www.apideck.com/blog/introduction-to-openapi-specification
- https://reflectoring.io/spring-boot-openapi/
- ChatGPT
Yazımızın teknik gözden geçirmesi için Deren Toy’a, editör desteği için ise Tuğçe Yılmaz’a teşekkür ederiz.