bible_api

repository·master·Indexed 21 days ago

https://github.com/seven1m/bible_api

A Ruby web application that serves a JSON API for public domain and open Bible translations, accessible via bible-api.com. It provides endpoints for retrieving specific verses by reference, fetching random verses, and exploring translation metadata. The project supports self-hosting on Linux with Ruby, Redis, and MySQL/MariaDB, and includes Rack::AbuseMiddleware for rate limiting based on 404 errors.

Tokens
3.3K
Snippets
13
Records
14
Agent score
74%

What's inside bible_api

  1. Deploy and rebuild the database on Dokku

    master

    If you are hosting bible_api on Dokku and need to rebuild the database (e.g., after a migration or initial setup), follow these steps to create a new database, import the data using the provided Ruby script, and promote the new database to production.

    Note: Replace bible_api_2024 with your desired database name and bible-api.com with your actual Dokku app name. Ensure you use the correct environment variable provided by Dokku for the DATABASE_URL during the import step.

    # 1. Create and link the new database
    dokku mysql:create bible_api_2024
    dokku mysql:link bible_api_2024 bible-api.com
    
    # 2. Enter the app container and run the import script
    dokku enter bible-api.com
    # Inside the container, use the Dokku-provided MySQL URL
    DATABASE_URL="$DOKKU_MYSQL_AQUA_URL" ruby import.rb
    exit
    
    # 3. Promote the new database to production
    dokku mysql:promote bible_api_2024 bible-api.com
    
    # 4. Cleanup old databases (optional)
    dokku mysql:unlink bible_api_2023 bible-api.com
    dokku mysql:stop bible_api_2023
    dokku mysql:destroy bible_api_2023
  2. Access the Bible API via HTTP

    master

    The Bible API is available at https://bible-api.com/. You can retrieve Bible verses by appending the reference (e.g., John+3:16) to the base URL. The API returns a JSON object containing the verse text, metadata, and translation information.

    curl -s https://bible-api.com/John+3:16 | jq
  3. Host the Bible API yourself

    master

    To self-host the bible_api, you need a Linux server with Ruby, Redis, and MySQL (or MariaDB) installed.

    1. Clone and Prepare

    git clone https://github.com/seven1m/bible_api
    cd bible_api
    git submodule update --init

    2. Install Dependencies

    gem install bundler
    bundle config --local deployment true
    bundle install

    3. Database Setup and Data Import

    First, create the MySQL database and user, then set the required environment variables before running the import script:

    mysql -uroot -e "create database bible_api; grant all on bible_api.* to user@localhost identified by 'password';"
    export DATABASE_URL="mysql2://user:password@localhost/bible_api"
    export REDIS_URL="redis://localhost:6379"
    bundle exec ruby import.rb

    4. Run the Application

    For testing, run:

    bundle exec ruby app.rb

    For production, it is recommended to use Passenger.

  4. How JSONP works in this API

    master

    The API supports JSONP for cross-origin requests. When using the jsonp helper, the response will be wrapped in a callback function. You can specify the callback name using the callback, jscallback, jsonp, or jsoncallback query parameters. If no callback is provided, the API defaults to standard application/json with UTF-8 charset.

    // Example JSONP request
    // GET /John+3:16?callback=myCallback
    
    myCallback({
      "reference": "John 3:16",
      "verses": [...],
      "text": "..."
    });
  5. Use the Bible API with Ruby

    master

    You can consume the API in Ruby using open-uri and json libraries. This is useful for quick scripts or integrating Bible data into Ruby applications.

    ruby -r open-uri -r json -r pp -e "pp JSON.parse(URI.open('https://bible-api.com/John+3:16').read)"
  6. Configure Rack::AbuseMiddleware for rate limiting

    master

    The Rack::AbuseMiddleware is a middleware used to prevent abuse by blocking IP addresses that trigger too many 404 (Not Found) errors within a specific time window. It requires a redis instance to track request counts and block status.

    Configuration Options

    When initializing the middleware, you can provide an options hash with the following keys:

    KeyTypeDefaultDescription
    :redisRedis instanceRequiredA connection to a Redis server used for state tracking.
    :limitInteger10The number of 404 errors allowed before the IP is blocked.
    :windowInteger30The time window (in seconds) for which 404 errors are counted.
    :block_timeInteger3600The duration (in seconds) for which an IP remains blocked after exceeding the limit.

    Behavior

    • IP Detection: Uses the HTTP_X_FORWARDED_FOR header (taking the first IP in the list) or REMOTE_ADDR.
    • Blocking: If an IP exceeds the :limit of 404 errors within the :window, it is flagged in Redis and will receive a 403 Forbidden response for the duration of :block_time.
    Rack::AbuseMiddleware.new(app, {
      redis: Redis.new,
      limit: 10,
      window: 30,
      block_time: 3600
    })
  7. Understand the Bible API JSON response format

    master

    The API returns a JSON object with the following structure:

    • reference: The Bible reference string (e.g., "John 3:16").
    • verses: An array of verse objects. Each object contains:
      • book_id: The abbreviated book name (e.g., "JHN").
      • book_name: The full book name (e.g., "John").
      • chapter: The chapter number.
      • verse: The verse number.
      • text: The verse text content.
    • text: A concatenated string of all requested verse texts.
    • translation_id: The ID of the translation used (e.g., "web").
    • translation_name: The name of the translation (e.g., "World English Bible").
    • translation_note: Notes regarding the translation's copyright status.
    {
      "reference": "John 3:16",
      "verses": [
        {
          "book_id": "JHN",
          "book_name": "John",
          "chapter": 3,
          "verse": 16,
          "text": "\nFor God so loved the world...\n\n"
        }
      ],
      "text": "\nFor God so loved the world...\n\n",
      "translation_id": "web",
      "translation_name": "World English Bible",
      "translation_note": "Public Domain"
    }
  8. Get all available translations via /data

    master

    To discover which Bible translations are available, call the /data endpoint. It returns a JSON object containing a list of translations. Each translation includes its identifier, name, language, language code, and a URL to access that specific translation's data.

    GET /data
    
    Response format:
    {
      "translations": [
        {
          "identifier": "WEB",
          "name": "World English Bible",
          "language": "English",
          "language_code": "en",
          "license": "...",
          "url": "https://api.example.com/data/WEB"
        }
      ]
    }
  9. Fetch specific verses by reference via /:ref

    master

    The primary endpoint for fetching specific verses or ranges is /:ref. The ref is a string representing the Bible reference (e.g., John 3:16 or John 3:16-18).

    Features:

    • Ranges: Supports ranges like John 3:16-18.
    • Chapter Limits: You cannot fetch more than one whole chapter at once (e.g., John 3:16-4:1 is allowed, but John 3:16-5:1 is blocked to prevent abuse).
    • Verse Numbers: If you pass the query parameter verse_numbers=true, the text field in the response will include the verse numbers in parentheses (e.g., (1) In the beginning...).
    • Single Chapter Matching: By default, a reference like Jude 1 refers to a single verse. If you want it to match the whole chapter, you must pass the query parameter single_chapter_book_matching=indifferent.
    GET /John+3:16-18
    GET /John+3:16?verse_numbers=true
    GET /Jude+1?single_chapter_book_matching=indifferent
    
    Response format:
    {
      "reference": "John 3:16-18",
      "verses": [
        { "book_id": "JHN", "book": "John", "chapter": 3, "verse": 16, "text": "For God so loved..." }
      ],
      "text": "For God so loved...",
      "translation_id": "WEB",
      "translation_name": "World English Bible",
      "translation_note": "..."
    }
  10. Retrieve verses for a chapter via /data/:translation/:book_id/:chapter

    master

    To fetch all verses within a specific chapter, use the /data/:translation/:book_id/:chapter endpoint. This returns an array of verse objects containing the text and reference information.

    GET /data/WEB/GEN/1
    
    Response format:
    {
      "translation": { ... },
      "verses": [
        { "book_id": "GEN", "book": "Genesis", "chapter": 1, "verse": 1, "text": "In the beginning..." },
        { "book_id": "GEN", "book": "Genesis", "chapter": 1, "verse": 2, "text": "And the earth..." }
      ]
    }
  11. List chapters in a book via /data/:translation/:book_id

    master

    To get a list of all chapters available in a specific book for a given translation, use the /data/:translation/:book_id endpoint. Each chapter object includes a URL to fetch the specific verses for that chapter.

    GET /data/WEB/GEN
    
    Response format:
    {
      "translation": { ... },
      "chapters": [
        { "book_id": "GEN", "book": "Genesis", "chapter": 1, "url": "https://api.example.com/data/WEB/GEN/1" },
        { "book_id": "GEN", "book": "Genesis", "chapter": 2, "url": "https://api.example.com/data/WEB/GEN/2" }
      ]
    }
  12. Get a random verse from a specific book or section via /data/:translation/random/:book_id

    master

    You can narrow down random verse selection by providing a book_id. You can also use special identifiers for sections:

    • OT: Old Testament
    • NT: New Testament
    • A comma-separated list of book IDs (e.g., GEN,EXO)
    • A single book_id (e.g., JHN)
    GET /data/WEB/random/OT
    GET /data/WEB/random/NT
    GET /data/WEB/random/GEN,EXO
    
    Response format:
    {
      "translation": { ... },
      "random_verse": { ... }
    }