Hono.js'ye Başlarken: Yeni Başlayanlar İçin Bir Rehber

Bu rehber, Hono.js'ye başlamak için gereken her şeyi anlatır: kurulumdan ilk uygulamaya, temel kavramlara kadar.

Efe Demir

Efe Demir

5 June 2025

Hono.js'ye Başlarken: Yeni Başlayanlar İçin Bir Rehber

```html

Web geliştirmenin hızla gelişen dünyasında, doğru framework'ü bulmak zorlayıcı olabilir. Hızlı, hafif ve farklı ortamlarda çalışacak kadar esnek bir şey istersiniz. İşte Hono – etkileyici hızı, minimum ayak izi ve geliştirici dostu tasarımıyla geliştiriciler arasında hızla popülerlik kazanan bir web framework'ü.

Hono (Japonca'da "alev" 🔥 anlamına gelir) adını hak ediyor – son derece hızlı ve zarif sadeliğiyle geliştirme deneyiminizi aydınlatıyor. İster API'ler, ister mikro hizmetler veya full-stack uygulamalar oluşturuyor olun, Hono daha ağır framework'lere cazip bir alternatif sunuyor.

Bu rehber, Hono.js'ye kurulumdan ilk uygulamanızı oluşturmaya ve temel kavramlarını anlamaya kadar bilmeniz gereken her şeyi size adım adım anlatacak.

💡
Harika bir API Test aracı mı istiyorsunuz? Güzel API Dokümantasyonu oluşturur?

Geliştirici Ekibinizin maksimum verimlilikle birlikte çalışması için entegre, Hepsi Bir Arada bir platform mu istiyorsunuz?

Apidog tüm taleplerinizi karşılıyor ve Postman'in yerini çok daha uygun bir fiyata alıyor!
button

Hono Nedir?

Hono, Web Standartları üzerine inşa edilmiş küçük, basit ve ultra hızlı bir web framework'üdür. Neredeyse her JavaScript çalışma zamanında çalışır: Cloudflare Workers, Fastly Compute, Deno, Bun, Vercel, Netlify, AWS Lambda, Lambda@Edge ve Node.js.

Temelinde Hono, Web Standartları API'lerini (Request, Response ve Fetch gibi) benimser, bu da ona platformlar arasında dikkate değer bir taşınabilirlik sağlar. Bu, kodunuzu bir kez yazıp büyük değişiklikler yapmadan neredeyse her yere dağıtabileceğiniz anlamına gelir.

import { Hono } from 'hono'
const app = new Hono()

app.get('/', (c) => c.text('Hono!'))

export default app

Bu basit örnek, Express'ten ilham alan ancak günümüzün JavaScript ekosistemi için modernize edilmiş Hono'nun temiz sözdizimini göstermektedir.

Hadi dalalım!

1. Hono.js'yi Bun ile Kurun ve Proje Kurulumu

Bun, bir paket yöneticisi, paketleyici ve test çalıştırıcısı dahil olmak üzere hızı ve hepsi bir arada araç takımıyla bilinen modern bir JavaScript çalışma zamanıdır. Hono'yu Bun ile kurmak basittir.

Önkoşullar

Bun'un yüklü olduğundan emin olun. Değilse, resmi Bun web sitesindeki talimatları izleyerek yükleyebilirsiniz.

Bun ile Yeni Bir Hono Projesi Oluşturma

Bun ile yeni bir Hono projesine başlamanın en hızlı yolu, create-hono iskele oluşturma aracını kullanmaktır:

bun create hono@latest my-hono-app

Bu komut, bir şablon seçmenizi ister. Bu rehber için bun şablonunu seçin.

? Which template do you want to use? › - Use arrow keys. Return to submit.
❯   bun
    cloudflare-workers
    cloudflare-pages
    deno
    fastly
    netlify
    nodejs
    vercel

Şablonu seçtikten sonra, yeni proje dizininize gidin ve bağımlılıkları yükleyin:

cd my-hono-app
bun install

Hono'yu Mevcut Bir Bun Projesine Ekleme

Mevcut bir Bun projeniz varsa, Hono'yu bir bağımlılık olarak ekleyebilirsiniz:

bun add hono

2. Hono.js ile Temel Bir Uygulama Oluşturma: "Merhaba Hono!"

Basit bir "Merhaba Dünya" (ya da daha doğrusu, "Merhaba Hono!") uygulaması oluşturalım.

Projenizin içinde bir src dizini olmalıdır. src/index.ts'yi (veya düz JavaScript tercih ediyorsanız index.js'yi, ancak Hono'nun tüm avantajları için TypeScript önerilir) oluşturun veya açın.

// src/index.ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.text('Hello Hono!')
})

export default app

Bunu parçalayalım:

  1. hono paketinden Hono sınıfını içe aktarıyoruz.
  2. Hono'nun yeni bir örneğini oluşturuyoruz, genellikle app olarak adlandırılır.
  3. Kök yola (/) yapılan GET istekleri için bir rota tanımlıyoruz.
  4. Rota işleyicisi, bir Context nesnesini (geleneksel olarak c) bir argüman olarak alan bir fonksiyondur.
  5. c.text('Hello Hono!'), "Merhaba Hono!" metnini içeren bir Response nesnesi oluşturur.
  6. Son olarak, app örneğini dışa aktarıyoruz. Bun için, bu varsayılan dışa aktarım, geliştirme sunucusunun onu alması için yeterlidir.

Uygulamanızı Çalıştırma

Uygulamanızı geliştirme modunda çalıştırmak için, package.json dosyanızda tanımlanan dev komut dosyasını kullanın (create-hono bunu sizin için ayarlar):

bun run dev

Bu genellikle bir sunucuyu http://localhost:3000 adresinde başlatır. Bu URL'yi web tarayıcınızda açın; "Merhaba Hono!" görmelisiniz.

Portu Değiştirme

Uygulamanızı farklı bir portta çalıştırmanız gerekiyorsa, src/index.ts içindeki dışa aktarımı değiştirebilirsiniz:

// src/index.ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.text('Hello Hono on port 8080!')
})

export default {
  port: 8080, // İstediğiniz portu belirtin
  fetch: app.fetch,
}

Şimdi, bun run dev komutunu çalıştırdığınızda, uygulama http://localhost:8080 adresinde hizmet verecektir.

3. Hono.js ile Temel Bir API Oluşturma

Hono, API'ler oluşturmada mükemmeldir. Yönlendirmeyi ve istekleri nasıl işleyeceğimizi ve yanıtlar oluşturacağımızı inceleyelim.

Yönlendirme

Hono'da yönlendirme sezgiseldir. app örneği, HTTP fiillerine karşılık gelen yöntemlere sahiptir (.get(), .post(), .put(), .delete(), vb.).

Temel GET Rotası

Zaten temel bir GET rotası gördük:

app.get('/hello', (c) => {
  return c.text('Hello, world!')
})

Yol Parametreleri

:paramName sözdizimini kullanarak yol parametreleri olan rotalar tanımlayabilirsiniz. Bu parametrelere c.req.param('paramName') aracılığıyla erişilebilir.

// Örnek: /users/123
app.get('/users/:id', (c) => {
  const userId = c.req.param('id')
  return c.text(`User ID: ${userId}`)
})

Sorgu Parametreleri

URL'den gelen sorgu parametrelerine (örneğin, /search?q=hono) c.req.query('queryName') kullanılarak erişilebilir.

// Örnek: /search?category=frameworks&limit=10
app.get('/search', (c) => {
  const category = c.req.query('category')
  const limit = c.req.query('limit')
  return c.text(`Searching in category: ${category}, Limit: ${limit}`)
})

Ayrıca, tüm sorgu parametrelerini c.req.query() ile bir nesne olarak alabilirsiniz.

Farklı HTTP Yöntemlerini İşleme

Hono, aynı yol için çeşitli HTTP yöntemlerini işlemeyi kolaylaştırır:

// src/index.ts
import { Hono } from 'hono'

const app = new Hono()

// GET a list of posts
app.get('/posts', (c) => {
  // Gerçek bir uygulamada, bunu bir veritabanından alırsınız
  const posts = [
    { id: '1', title: 'Getting Started with Hono' },
    { id: '2', title: 'Advanced Hono Techniques' },
  ];
  return c.json(posts); // JSON yanıtı döndür
})

// GET a single post by ID
app.get('/posts/:id', (c) => {
  const id = c.req.param('id')
  // Fetch post by ID from a database
  const post = { id: id, title: `Post ${id}`, content: 'This is the content...' };
  if (!post) {
    return c.notFound() // 404 için yerleşik yardımcı
  }
  return c.json(post)
})

// CREATE a new post
app.post('/posts', async (c) => {
  const body = await c.req.json() // JSON gövdesini ayrıştır
  // Gerçek bir uygulamada, bunu bir veritabanına kaydedersiniz
  console.log('Creating post:', body)
  return c.json({ message: 'Post created successfully!', data: body }, 201) // 201 Created ile yanıt ver
})

// UPDATE an existing post
app.put('/posts/:id', async (c) => {
  const id = c.req.param('id')
  const body = await c.req.json()
  // Update post in database
  console.log(`Updating post ${id}:`, body)
  return c.json({ message: `Post ${id} updated successfully!`, data: body })
})

// DELETE a post
app.delete('/posts/:id', (c) => {
  const id = c.req.param('id')
  // Delete post from database
  console.log(`Deleting post ${id}`)
  return c.json({ message: `Post ${id} deleted successfully!` })
})


export default {
  port: 3000,
  fetch: app.fetch
}

İstek Nesnesi (c.req)

Context nesnesi (c), c.req aracılığıyla istek ayrıntılarına erişim sağlar. Temel özellikleri ve yöntemleri şunlardır:

Yanıt Nesnesi (c) ve Yardımcılar

Context nesnesi (c) ayrıca Response nesneleri oluşturmak için kullanışlı yardımcılar sağlar:

Örnek: Özel Başlıklar Ayarlama

app.get('/custom-header', (c) => {
  c.header('X-Powered-By', 'HonoJS-Flame')
  c.header('Cache-Control', 'no-cache')
  return c.text('Check the response headers!')
})

4. Hono.js'de Middleware ile Çalışmak

Middleware fonksiyonları, Hono'nun (ve birçok web framework'ünün) temel taşıdır. Bunlar, bir isteği ana rota işleyicisine ulaşmadan önce veya işleyici çalıştıktan sonra bir yanıtı işleyebilen fonksiyonlardır. Middleware, günlüğe kaydetme, kimlik doğrulama, veri doğrulama, sıkıştırma, CORS ve daha fazlası gibi görevler için harikadır.

Bir middleware fonksiyonunun temel imzası async (c, next) => { ... }'dir.

Yerleşik Middleware'i Kullanma

Hono, zengin bir yerleşik middleware kümesiyle birlikte gelir. Bunları hono/middleware-name'den (örneğin, hono/logger, hono/cors) içe aktarabilirsiniz.

Middleware'i tüm rotalara uygulamak için app.use(middlewareFunction) kullanın.
Middleware'i belirli rotalara uygulamak için ilk argüman olarak bir yol deseni sağlayın: app.use('/admin/*', authMiddleware).

Örnek: Logger ve ETag Middleware

// src/index.ts
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { etag } from 'hono/etag'
import { prettyJSON } from 'hono/pretty-json' // Güzelce biçimlendirilmiş JSON yanıtları için

const app = new Hono()

// Middleware'i tüm rotalara uygula
app.use(logger()) // İstek ve yanıt bilgilerini konsola kaydeder
app.use(etag())   // Önbelleğe alma için ETag başlıkları ekler
app.use(prettyJSON()) // JSON yanıtlarını girintilerle biçimlendirir

app.get('/', (c) => {
  return c.text('Hello with Logger and ETag!')
})

app.get('/data', (c) => {
  return c.json({ message: 'This is some data.', timestamp: Date.now() })
})

export default app

Bunu çalıştırdığınızda ve / veya /data'ya eriştiğinizde, konsolunuzda günlükleri göreceksiniz ve yanıtlar bir ETag başlığı içerecektir. /data'dan gelen JSON yanıtları güzelce biçimlendirilecektir.

Diğer Faydalı Yerleşik Middleware:

"Middleware" altında Hono belgelerinde tam bir liste ve dokümantasyon bulabilirsiniz.

Özel Middleware Oluşturma

Kendi middleware'inizi kolayca yazabilirsiniz.

Örnek 1: Basit İstek Zamanlayıcısı

// src/index.ts
import { Hono } from 'hono'
import { logger } from 'hono/logger'

const app = new Hono()

app.use(logger())

// İstek işleme süresini ölçmek için özel middleware
app.use(async (c, next) => {
  const start = Date.now()
  console.log(`Request received at: ${new Date(start).toISOString()}`)
  await next() // Bir sonraki middleware'i veya rota işleyicisini çağırın
  const ms = Date.now() - start
  c.header('X-Response-Time', `${ms}ms`) // Yanıta özel başlık ekleyin
  console.log(`Request processed in ${ms}ms`)
})

app.get('/', (c) => {
  return c.text('Hello from Hono with custom timing middleware!')
})

app.get('/slow', async (c) => {
  // Yavaş bir işlemi simüle et
  await new Promise(resolve => setTimeout(resolve, 1500))
  return c.text('This was a slow response.')
})

export default app

Zamanlama günlüklerini ve X-Response-Time başlığını görmek için / ve /slow'a erişin.

Örnek 2: Basit API Anahtarı Kimlik Doğrulama Middleware'i

Bu, gösteri amaçlı çok basit bir örnektir. Gerçek bir uygulamada, JWT veya OAuth gibi daha sağlam kimlik doğrulama yöntemleri kullanın ve API anahtarlarını güvenli bir şekilde saklayın.

// src/index.ts
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { HTTPException } from 'hono/http-exception' // Standart HTTP hataları atmak için

const app = new Hono()

app.use(logger())

const API_KEY = "supersecretapikey"; // Gerçek bir uygulamada, bunu güvenli bir şekilde saklayın (örneğin, env değişkeni)

// Özel API Anahtarı Kimlik Doğrulama Middleware'i
const apiKeyAuth = async (c, next) => {
  const apiKeyHeader = c.req.header('X-API-KEY')
  if (apiKeyHeader && apiKeyHeader === API_KEY) {
    await next()
  } else {
    // Standart bir hata yanıtı döndürmek için HTTPException kullanma
    throw new HTTPException(401, { message: 'Unauthorized: Invalid API Key' })
  }
}

// Bu middleware'i belirli bir rota grubuna uygulayın
app.use('/api/v1/*', apiKeyAuth)

app.get('/api/v1/me', (c) => {
  return c.json({ user: 'Authenticated User', email: 'user@example.com' })
})

app.get('/public/info', (c) => {
  return c.text('This is public information, no API key needed.')
})

// HTTPException için hata işleyici
app.onError((err, c) => {
  if (err instanceof HTTPException) {
    return err.getResponse()
  }
  // Diğer hatalar için
  console.error('Unhandled error:', err)
  return c.text('Internal Server Error', 500)
})


export default app

Bunu test etmek için:

createMiddleware ile Özel Middleware'i Yeniden Kullanma

Daha karmaşık veya yeniden kullanılabilir middleware için, hono/factory'den createMiddleware kullanarak ayrı olarak tanımlayabilirsiniz. Bu aynı zamanda TypeScript tür çıkarımına da yardımcı olur.

// src/middlewares/timing.ts
import { createMiddleware } from 'hono/factory'

export const timingMiddleware = createMiddleware(async (c, next) => {
  const start = Date.now()
  await next()
  const ms = Date.now() - start
  c.res.headers.set('X-Response-Time', `${ms}ms`) // Not: c.res.headers.set
  console.log(` -> Processed in ${ms}ms`)
})

// src/middlewares/auth.ts
import { createMiddleware } from 'hono/factory'
import { HTTPException } from 'hono/http-exception'

const VALID_API_KEY = "anothersecretkey";

// Middleware'inizin ihtiyacı varsa ortam değişkenleri için tür
type Env = {
  Variables: {
    user?: { id: string } // Örnek: kimlik doğrulama sonrası kullanıcı verilerini ayarlayın
  }
  // Bindings: { MY_KV_NAMESPACE: KVNamespace } // Örnek: Cloudflare Workers için
}

export const secureApiKeyAuth = createMiddleware<Env>(async (c, next) => {
  const apiKey = c.req.header('Authorization')?.replace('Bearer ', '')
  if (apiKey === VALID_API_KEY) {
    // İsteğe bağlı olarak, alt akış işleyicileri için bağlamda değişkenler ayarlayabilirsiniz
    c.set('user', { id: 'user123' })
    await next()
  } else {
    throw new HTTPException(401, { message: 'Access Denied: Secure API Key Required.'})
  }
})


// src/index.ts
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { timingMiddleware } from './middlewares/timing' // Middlewares klasöründe olduklarını varsayarak
import { secureApiKeyAuth } from './middlewares/auth'

const app = new Hono()

app.use(logger())
app.use(timingMiddleware) // Tüm rotalara uygula

app.get('/', (c) => {
  return c.text('Hello from Hono with factored middleware!')
})

app.use('/secure/data/*', secureApiKeyAuth) // Yalnızca /secure/data/* için uygula
app.get('/secure/data/profile', (c) => {
  // const user = c.get('user') // Middleware tarafından ayarlanan değişkene erişin
  return c.json({ profileData: 'Sensitive profile information', /*user: user*/ })
})

app.get('/public/data', (c) => {
  return c.text('This is public data, no key needed.')
})

// Genel hata işleyici
app.onError((err, c) => {
  if (err instanceof HTTPException) {
    return err.getResponse();
  }
  console.error('Error:', err.message);
  return c.json({ error: 'Internal Server Error', message: err.message }, 500);
});

export default app

Bu yapı, middleware'inizi daha modüler hale getirir ve bağımsız olarak test etmeyi kolaylaştırır.

5. Hono.js Uygulamalarınızı Test Etme

Hono, kolayca test edilebilir olacak şekilde tasarlanmıştır. Bun, Hono ile iyi çalışan kendi test çalıştırıcısı bun:test ile birlikte gelir. Ayrıca Vitest gibi diğer test çalıştırıcılarını da kullanabilirsiniz.

bun:test'i Kullanma (Temel)

bun.md dokümantasyonu, bun:test ile test etmenin temel bir örneğini sağlar:

Örneğin, src/index.test.ts adlı bir test dosyası oluşturun:

// src/index.test.ts
import { describe, expect, it } from 'bun:test'
import app from '.' // Uygulamanızı src/index.ts'den içe aktarır

describe('Hono Uygulama Testleri', () => {
  it('GET / için 200 OK döndürmelidir', async () => {
    const req = new Request('http://localhost/') // Temel URL burada çok önemli değil
    const res = await app.fetch(req)
    expect(res.status).toBe(200)
    expect(await res.text()).toBe('Hello Hono!') // Veya kök rotanızın döndürdüğü her neyse
  })

  it('GET /posts için JSON döndürmelidir', async () => {
    const req = new Request('http://localhost/posts')
    const res = await app.fetch(req)
    expect(res.status).toBe(200)
    const json = await res.json()
    expect(json).toBeArray() // /posts bir dizi döndürdüğünü varsayarak
    // Gerekirse JSON içeriği hakkında daha özel iddialar ekleyin
  })

  it('POST /posts için bir gönderi oluşturmalıdır', async () => {
    const postData = { title: 'Test Post', content: 'This is a test.' };
    const req = new Request('http://localhost/posts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(postData),
    });
    const res = await app.fetch(req);
    expect(res.status).toBe(201); // 201 Created bekleyin
    const jsonResponse = await res.json();
    expect(jsonResponse.message).toBe('Post created successfully!');
    expect(jsonResponse.data.title).toBe(postData.title);
  });
})

Testlerinizi çalıştırmak için:

bun test

Veya, belirli bir dosyayı çalıştırmak istiyorsanız:

bun test src/index.test.ts

app.request() Yardımcısını Kullanma

Hono, her seferinde tam bir Request nesnesi oluşturmak yerine, doğrudan bir yol ve seçenekler geçirmenize izin vererek test etmeyi basitleştiren kullanışlı bir app.request() yöntemi sağlar. Bu, docs/guides/testing.md'de gösterilmektedir.

// src/index.test.ts
import { describe, expect, it } from 'bun:test' // Veya 'vitest'ten içe aktarın
import app from '.' // Hono uygulamanızın örneği

describe('app.request() ile Hono Uygulaması', () => {
  it('GET / "Merhaba Hono!" döndürmelidir', async () => {
    const res = await app.request('/')
    expect(res.status).toBe(200)
    expect(await res.text()).toBe('Hello Hono!') // Kök yanıtınıza göre ayarlayın
  })

  it('GET /posts/:id belirli bir gönderiyi döndürmelidir', async () => {
    // Uygulamanızın app.get('/posts/:id', ...) gibi bir rotası olduğunu varsayarak
    // ve bu test için, { id: '123', title: 'Test Post 123' } döndürebilir
    const res = await app.request('/posts/123')
    expect(res.status).toBe(200)
    const data = await res.json()
    expect(data.id).toBe('123')
    // expect(data.title).toBe('Post 123') // Veya uygulamanızın mantığına göre
  })

  it('POST /posts yeni bir gönderi oluşturmalıdır', async () => {
    const newPost = { title: 'My New Post', content: 'Awesome content here.' }
    const res = await app.request('/posts', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(newPost),
    })
    expect(res.status).toBe(201) // POST /posts'unuzun 201 döndürdüğünü varsayarak
    const responseData = await res.json()
    expect(responseData.message).toBe('Post created successfully!')
    expect(responseData.data.title).toBe(newPost.title)
  })

  it('API anahtarı olmadan GET /api/v1/me 401 olmalıdır', async () => {
    // Önceki örnekten API anahtarı middleware'inin bu rotada etkin olduğunu varsayarak
    const res = await app.request('/api/v1/me')
    expect(res.status).toBe(401)
  })

  it('Doğru API anahtarıyla GET /api/v1/me 200 olmalıdır', async () => {
    const res = await app.request('/api/v1/me', {
      headers: {
        'X-API-KEY': 'supersecretapikey' // Middleware'inizden anahtarı kullanın
      }
    })
    expect(res.status).toBe(200)
    const data = await res.json();
    expect(data.user).toBe('Authenticated User')
  })
})

Explore more

Fathom-R1-14B: Hindistan'dan Gelişmiş Yapay Zeka Muhakeme Modeli

Fathom-R1-14B: Hindistan'dan Gelişmiş Yapay Zeka Muhakeme Modeli

Yapay zeka hızla gelişiyor. FractalAIResearch/Fathom-R1-14B, 14.8 milyar parametreyle matematik ve genel akıl yürütmede başarılı.

5 June 2025

Mistral Code: İşletmeler için En Özelleştirilebilir Yapay Zeka Destekli Kodlama Asistanı

Mistral Code: İşletmeler için En Özelleştirilebilir Yapay Zeka Destekli Kodlama Asistanı

Mistral Code'u keşfedin: Kurumsal kullanıma özel, en özelleştirilebilir yapay zeka destekli kodlama asistanı.

5 June 2025

Claude Code'un 2025'te Yapay Zeka Kodlamasını Nasıl Dönüştürdüğü

Claude Code'un 2025'te Yapay Zeka Kodlamasını Nasıl Dönüştürdüğü

Claude Code, 2025'te yapay zeka destekli kodlamayı nasıl devrimleştiriyor? Özelliklerini, kullanımını ve Windsurf kısıtlamalarından sonra neden popüler olduğunu öğrenin. Geliştiriciler için okunması gereken!

5 June 2025

API Tasarım-Öncelikli Yaklaşımı Apidog'da Uygulayın

API'leri oluşturmanın ve kullanmanın daha kolay yolunu keşfedin