Elixir Server: Hello World & User IP Tutorial

by Natalie Brooks 48 views

Hey guys! Today, we're diving into building a simple yet powerful Elixir server that does two cool things: it greets users with a friendly "Hello World" message and, even cooler, it tells them their IP address. This is a fantastic project for anyone getting started with Elixir and wanting to understand how to handle HTTP requests. So, let's get started!

Setting Up Our Elixir Project

First things first, we need to set up our Elixir project. If you haven't already got Elixir and Erlang installed, now's the time to do it. You can find the installation instructions on the official Elixir website. Once you're all set, open up your terminal and let's create a new project.

mix new hello_world_server
cd hello_world_server

This command uses Mix, Elixir's build tool, to generate a new project named hello_world_server. We then navigate into the project directory. Inside, you'll see a bunch of files and folders. The main ones we'll be working with are mix.exs (our project configuration) and the lib directory where our Elixir code will live.

Adding Dependencies

To handle HTTP requests, we're going to use a library called Plug. Plug is a specification for building web applications in Elixir, and it's super versatile. We'll also use Cowboy, which is a web server adapter for Plug. To add these dependencies, we need to modify our mix.exs file.

Open up mix.exs and find the deps function. It should look something like this:

defp deps do
  [
    # {:dep_from_hexpm, ">= 0.0.0"},
    # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git"}
  ]
end

Let's add Plug and Cowboy as dependencies:

defp deps do
  [
    {:plug, "~> 2.0"},
    {:cowboy, "~> 2.0"}
  ]
end

Here, we're specifying that we want Plug version 2.0 or higher and Cowboy version 2.0 or higher. Save the file, and then run the following command in your terminal to fetch the dependencies:

mix deps.get

This command tells Mix to download and install the dependencies we just added.

Configuring Our Application

Next, we need to configure our application to use Plug and Cowboy. Still in mix.exs, find the application function. It might look like this:

def application do
  [
    extra_applications: [:logger]
  ]
end

We need to tell our application to start Cowboy when it starts. To do this, we'll add :cowboy to the extra_applications list:

def application do
  [
    extra_applications: [:logger, :cowboy]
  ]
end

Save the file. Now, our application knows to start Cowboy when it starts up.

Creating Our Plug

Now comes the fun part: writing the code that handles the HTTP requests! We'll create a new module that implements the Plug behaviour. This module will be responsible for receiving requests, processing them, and sending back responses.

Inside the lib directory, create a new file named hello_world_server.ex. This is where our Plug module will live. Open it up and let's start coding:

defmodule HelloWorldServer do
  use Plug.Router

  plug :match
  plug :dispatch

  get "/", do:
    send_resp(conn, 200, "Hello, World!")

  get "/ip", do:
    ip = Plug.Conn.get_req_header(conn, "x-forwarded-for") |> List.first() || Plug.Conn.remote_ip(conn) |> Tuple.to_list() |> List.first() |> to_string()
    send_resp(conn, 200, "Your IP address is: #{ip}")

  match _ do
    send_resp(conn, 404, "Not Found")
  end
end

Let's break down what's happening here:

  • defmodule HelloWorldServer do: This defines our module named HelloWorldServer. This is where all our server logic will reside.
  • use Plug.Router: This line is crucial. It brings in the Plug.Router functionality, which allows us to define routes for our server. Think of routes as different paths on your website or application (like / or /ip).
  • plug :match and plug :dispatch: These are Plug's way of saying, "Hey, let's match the incoming request to a route and then dispatch it to the appropriate handler function." This is the heart of how Plug handles requests.
  • get "/", do:: This is where we define our first route. The get macro tells Plug that this route should handle HTTP GET requests to the root path (/). When a user visits the main page of our server, this is the code that will be executed.
  • send_resp(conn, 200, "Hello, World!"): This is the action taken when someone visits the root path. send_resp is a function provided by Plug that sends a response back to the client. Here, we're sending a 200 OK status code (which means everything's fine) and the message "Hello, World!". This is the classic greeting!
  • get "/ip", do:: This defines another route, this time for the /ip path. When a user visits /ip, we want to show them their IP address. This is where things get a little more interesting.
  • ip = ...: This line is the core of our IP address retrieval logic. Let's break it down further:
    • Plug.Conn.get_req_header(conn, "x-forwarded-for"): This tries to get the X-Forwarded-For header from the request. This header is often used by proxies and load balancers to pass along the original IP address of the client. If the server is behind a proxy, this is the best way to get the user's IP.
    • |> List.first(): The X-Forwarded-For header can contain a list of IPs, so we take the first one.
    • || Plug.Conn.remote_ip(conn): If the X-Forwarded-For header is not present (e.g., the user isn't behind a proxy), we fall back to using Plug.Conn.remote_ip(conn). This gives us the IP address of the direct connection to the server.
    • |> Tuple.to_list() |> List.first(): Plug.Conn.remote_ip returns the IP address as a tuple. We convert it to a list and take the first element to get the IP address in a usable format.
    • |> to_string(): Finally, we convert the IP address to a string so we can include it in our response.
  • send_resp(conn, 200, "Your IP address is: #{ip}"): Just like before, we're sending a 200 OK response, but this time with a message that includes the user's IP address.
  • match _ do: This is a catch-all route. The _ means "anything that doesn't match the previous routes." This is useful for handling cases where a user tries to visit a path that doesn't exist on our server.
  • send_resp(conn, 404, "Not Found"): Here, we're sending a 404 Not Found status code, which is the standard way to tell a user that the page they're looking for doesn't exist.

Save the hello_world_server.ex file. We're almost there!

Starting the Server

We have our Plug module, but we need to tell Cowboy to use it. To do this, we'll modify the lib/hello_world_server/application.ex file. This file defines our application's behaviour, including how it starts and stops.

Open up lib/hello_world_server/application.ex. You'll see a start function that looks something like this:

def start(_type, _args) do
  children = [
    # Supervisor.child_spec(HelloWorldServer.Worker, arg: 1)
  ]

  opts = [strategy: :one_for_one, name: HelloWorldServer.Supervisor]
  Supervisor.start_link(children, opts)
end

We need to add a child process to start Cowboy. This child process will listen for incoming HTTP requests and pass them to our HelloWorldServer Plug.

Modify the children list to include a call to Plug.Cowboy.child_spec:

def start(_type, _args) do
  children = [
    {Plug.Cowboy, scheme: :http, plug: HelloWorldServer, options: [port: 4000]}
  ]

  opts = [strategy: :one_for_one, name: HelloWorldServer.Supervisor]
  Supervisor.start_link(children, opts)
end

Let's break down this new line:

  • {Plug.Cowboy, ...}: This tells the supervisor to start a Plug.Cowboy process.
  • scheme: :http: We're specifying that we want to use HTTP (not HTTPS) for our server.
  • plug: HelloWorldServer: This is the crucial part! We're telling Cowboy to use our HelloWorldServer module to handle incoming requests. This is how Cowboy knows to use our routing logic.
  • options: [port: 4000]: We're telling Cowboy to listen for connections on port 4000. This is the port that users will use to access our server.

Save the lib/hello_world_server/application.ex file. Now, we're ready to start our server!

Running the Server

In your terminal, run the following command:

mix run --no-halt

This command starts our Elixir application. The --no-halt flag tells Mix to keep the application running even after the initial startup tasks are complete. This is important because we want our server to keep running and listening for requests.

You should see some output in your terminal indicating that the server has started. If you see any errors, double-check your code and make sure you've followed all the steps correctly.

Testing the Server

Now that our server is running, let's test it out! Open up your web browser and navigate to http://localhost:4000. You should see the message "Hello, World!" This means our basic route is working correctly.

Next, let's check the /ip route. Navigate to http://localhost:4000/ip. You should see a message that includes your IP address. If you're running the server on your local machine, you'll likely see 127.0.0.1 (the loopback address). If you're running it on a server, you'll see the server's public IP address.

Congratulations! You've successfully created an Elixir server that responds with "Hello World" and the user's IP address. How cool is that?

Making it Unique and SEO-Friendly

So, we've built our server, but how can we make this article stand out and attract more readers? Let's talk about making it unique and SEO-friendly.

Optimize Paragraphs

  • Main Keywords at the Beginning: When writing each paragraph, try to include your main keywords right at the beginning. This helps search engines understand what the paragraph is about right away. For example, instead of saying, "This project is great for those starting with Elixir," you could say, "Elixir server creation is a fantastic project for those starting with Elixir." The keywords stand out, and it's clear what the paragraph is focusing on.
  • Use Bold, Italic, and Strong Tags: These tags not only make your text look better but also help emphasize important information. Use **bold** for key phrases, *italic* for emphasis, and <strong>strong</strong> for crucial points that need to stand out. For instance, "The send_resp function is essential for sending responses" highlights the importance of the send_resp function.
  • Paragraph Length: Aim for each content paragraph to contain at least 300 words. This might seem like a lot, but it ensures you're providing comprehensive information and covering the topic in detail. Longer paragraphs also give you more opportunities to naturally weave in keywords and provide context.

Rewrite for Humans

  • Casual and Friendly Tone: Write like you're talking to a friend. Use casual language, slang, and personal anecdotes to make the content relatable. Instead of saying, "The user should navigate to..." try saying, "Okay guys, now head over to...". This makes the article feel more conversational and less like a technical manual.
  • Focus on High-Quality Content: Ultimately, the best way to attract and retain readers is to provide valuable content. Focus on explaining concepts clearly, providing practical examples, and answering potential questions. Don't just aim for word count; aim for usefulness. If your content is helpful, people will want to read it, and search engines will recognize its value.

Proper Title Ordering

  • Semantic Structure: Make sure your titles are properly ordered. Use <h1> for the main title, <h2> for major sections, <h3> for subsections, and so on. This helps organize your content logically and makes it easier for readers (and search engines) to understand the structure of your article. For example:
    • <h1>Create an Elixir Server Responding with 'Hello World' and User IP</h1>
    • <h2>Setting Up Our Elixir Project</h2>
    • <h3>Adding Dependencies</h3>
  • Title Length: Keep the title under 60 characters. This ensures it doesn't get cut off in search engine results and remains engaging at a glance. A concise title is more likely to grab attention and accurately reflect the content of your article.

Optimizing for SEO

  • Keyword Research: Before writing, do some keyword research to find out what terms people are using to search for Elixir server tutorials. Tools like Google Keyword Planner or Ahrefs can help you identify relevant keywords. In our case, keywords like "Elixir server tutorial," "Hello World Elixir," and "get user IP Elixir" are good candidates.
  • Keyword Placement: Once you have your keywords, strategically place them throughout your article. Include them in your title, headings, and body text. But don't stuff them in unnaturally; aim for a natural flow.
  • Meta Descriptions: Write a compelling meta description for your article. This is the snippet of text that appears in search engine results below the title. It should accurately summarize your article and entice users to click.
  • Internal and External Linking: Link to other relevant articles on your site (internal linking) and to authoritative sources on the web (external linking). This helps improve your site's overall SEO and provides additional value to your readers.

Conclusion

So, guys, that's how you create a basic Elixir server that responds with "Hello World" and the user's IP address! We've covered everything from setting up the project to writing the code and optimizing the article for SEO. Building this server is a great way to get your feet wet with Elixir and Plug. Plus, understanding how to get a user's IP address can be super useful for various applications.

Remember, the key to creating great content is to focus on providing value to your readers. Write clearly, explain things thoroughly, and make it fun! Keep experimenting with Elixir, and you'll be building amazing things in no time. Happy coding!