Skip to content

Commit

Permalink
up
Browse files Browse the repository at this point in the history
  • Loading branch information
gqcn committed Nov 26, 2024
1 parent 6b49a37 commit bd4dd74
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 216 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ keywords: [GoFrame framework, Web Server, Go language, modular framework, route
description: "Building a simple 'Hello World' Web Server using the GoFrame framework. GoFrame is a modular Go language framework that offers a convenient way to construct a web server. This article provides a detailed analysis of the code example, including the creation of a Server object, route binding, port setting, and interpretation of the running results, offering a quick start path for beginners."
---

`GoFrame` is a modular framework with well-developed infrastructure, where the `Web Server` module is a core component. We will take `Web` service development as an entry point for the framework, making it easier to learn and understand.
The `Web Server` module is a core component of `GoFrame`, a comprehensive modular framework. We'll start our journey with web service development, as it's an excellent way to introduce the framework's capabilities.

## Hello World

Let's develop a simple `Web Server` program.
Let's create a simple web server:

```go title="main.go"
package main
Expand All @@ -30,16 +30,17 @@ func main() {
s.Run()
}
```
Let's look at this piece of code:
- At any time, you can obtain a default `Server` object through the `g.Server()` method, which is designed using a **singleton pattern**. This means that multiple calls to this method return the same `Server` object. The `g` component is a framework-provided coupling component that encapsulates and initializes some commonly used component objects, providing convenience for business projects.
- Bind routes and callback functions through the `BindHandler` method of the `Server` object. In this example, we bound the `/` route and specified the callback function to return `Hello World`.
- In the callback function, the input parameter is the current request object `r *ghttp.Request`, which contains the context information of the current request. In this example, we directly `Write` the return result using `r.Response`.
- Set the current `Server` listening port using the `SetPort` method. In this example, we listen to port `8000`. If no port is set, it will default to a random port.
- Execute the `Server` listening and running using the `Run()` method blocking execution.

## Execution Result
Let's break down this code:
- The `g.Server()` method returns a default `Server` object implemented as a **singleton**. This means multiple calls return the same instance. The `g` package is a convenience wrapper that initializes and provides access to commonly used components.
- Routes and their handlers are registered using the `Server` object's `BindHandler` method. In this example, we've mapped the root path `/` to a handler that returns "Hello World".
- The handler function receives a `*ghttp.Request` parameter (`r`) containing the current request's context. Here, we use `r.Response.Write` to send our response.
- The `SetPort` method configures the server's listening port (8000 in this case). If not specified, a random port is assigned.
- Finally, the `Run()` method starts the server and blocks until the program is terminated.

Run the program, and you will see logs similar to the following in the terminal:
## Running the Server

When you run the program, you'll see output similar to this in your terminal:
```html
$ go run main.go
2024-10-27 21:30:39.412 [INFO] pid[58889]: http server started listening on [:8000]
Expand All @@ -51,22 +52,22 @@ $ go run main.go
----------|--------|-------|-----------------|-------------
```

The default log output contains the following information:
- Current process ID `58889`, and the listening address `:8000` (indicating that all IP addresses of the local machine are being monitored on port `8000`).
- Since the framework comes with an automatic API documentation generation feature, it is not enabled in this example, so it prompts `openapi specification is disabled`. The automatic generation of the API documentation will be explained in detail in the corresponding chapter of the development manual, which is not covered in this example.
- Finally, the current `Server` route list is printed. Since we only monitor the `/` route, only one route information is printed here. In the route information table:
- `ADDRESS`: Indicates the listening address of this route. The same process can run multiple `Server` instances simultaneously, with different `Server` instances listening to different addresses.
- `METHOD`: Indicates the `HTTP Method` information that the route monitors, such as `GET/POST/PUT/DELETE`, etc. Here `ALL` signifies listening for all `HTTP Methods`.
- `ROUTE`: Indicates the specific route address information being monitored.
- `HANDLER`: Denotes the name of the route callback function. Since this example uses a closure function, it shows a temporary function name `main.main.func1`.
- `MIDDLEWARE`: Indicates the name of the middleware function bound to the current route. Middleware is a classic interceptor in the `Server`, which will be explained in detail in later chapters, so it is not introduced here.
The output provides several key pieces of information:
- Process ID (`58889`) and listening address (`:8000`, which means the server is listening on all local IP addresses on port `8000`)
- A notice about OpenAPI specification being disabled (the framework includes automatic API documentation generation, which we'll cover in detail later)
- A routing table showing:
- `ADDRESS`: The listening address for each route. Note that a single process can host multiple `Server` instances, each with its own address
- `METHOD`: The HTTP methods the route handles (`ALL` means it accepts any method: GET, POST, PUT, DELETE, etc.)
- `ROUTE`: The URL path pattern
- `HANDLER`: The route's callback function name (shown as `main.main.func1` since we used an anonymous function)
- `MIDDLEWARE`: Any middleware attached to the route (we'll cover middleware, a powerful request interceptor feature, in later chapters)

After running, try visiting http://127.0.0.1:8000/, and you will see the output on the page.
Visit http://127.0.0.1:8000/ in your browser to see the result:

![img_1.png](img_1.png)

## Learning Summary
## What's Next

Congratulations! You have learned to use the `GoFrame` framework to develop your first `Web Server` program!
Great job! You've just created your first web server with `GoFrame`!

Next, we will try to obtain the parameter information submitted by the client in the `Web Server`.
In the next section, we'll explore how to handle client-submitted data in your web server.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ keywords: [GoFrame,GoFrame Framework,Web Server,Documents,Modular Design,Low Cou
description: "Quickly understand the development process and features of the Web Server API by viewing the Documents sections to resolve any doubts. GoFrame is a low-coupling, modular design framework with independent module designs, and independently written documentation. The community provides introductory video tutorials, and later a complete business project will be developed using the GoFrame framework project scaffold."
---

## Learning Summary
Through the quick sections, you should have understood the complete development process of the `Web Server` API and mastered some practical features. In these sections, we only touched on them briefly; for more detailed explanations and introductions to functional features, please refer to the corresponding Documents sections. When you feel confused about the use of a particular module, it is recommended to carefully read the corresponding Documents sections, which provide detailed explanations of the important functional features, usage methods, and common issues of each component.
## What You've Learned
By now, you should have a solid understanding of building Web APIs with `GoFrame` and have hands-on experience with its key features. While we've covered the basics in these quick-start guides, there's much more to explore. For in-depth explanations and advanced features, check out the relevant sections in our main documentation. If you ever find yourself stuck with a particular module, the documentation provides detailed insights into each component's functionality, usage patterns, and common pitfalls.

:::info
If you start browsing the Documents, it should be noted that since `GoFrame` is a low-coupling, modular design, each module is relatively independent. Therefore, the documentation in the Documents is also written based on modularity, with each chapter introducing only the usage of the corresponding component itself.
As you dive into the documentation, keep in mind that `GoFrame` follows a modular, loosely coupled design philosophy. Each module is designed to work independently, and our documentation reflects this approach - each chapter focuses specifically on its respective component.
:::

What should we do next?
So, what comes next?

## Project Scaffold
## Building Real Applications

In the upcoming sections, we will attempt to use the project scaffold provided by the `GoFrame` framework to develop a simple and relatively complete business project.
In the upcoming sections, we'll walk through building a complete business application using the `GoFrame` project scaffold. This hands-on tutorial will show you how to put everything together in a real-world context.
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,40 @@ keywords: [GoFrame, GoFrame Framework, Install GoFrame, Modular Framework, Low C
description: "Quick start guide for the GoFrame framework. GoFrame is a modular, low coupling design development framework that includes common basic components and development tools. It's suitable for complete business project frameworks and independent component libraries. The content covers downloading and installing GoFrame, running basic operations, and introducing how to develop simple Web Server API applications."
---

Hello everyone, welcome to the quick start chapter of the `GoFrame` framework! Because `GoFrame` is a modular, low coupling design development framework that includes common basic components and development tools, it can be used either as a complete business project framework or as an independent component library.
Welcome to the `GoFrame` Quick Start Guide! `GoFrame` is a modern Go framework designed with modularity and loose coupling in mind. You can use it either as a full-featured application framework or cherry-pick individual components for your specific needs.

In this chapter, we start from downloading, installing, and using the framework to guiding you in completing a relatively complete `Web Server` API development.
This guide will walk you through installing and setting up `GoFrame`, culminating in building your first web service.

:::info
If you are not ready for the `Go` language development environment, it is recommended that you first refer to the environment installation documentation: [Environment Preparation](../../docs/其他资料/准备工作/准备工作.md) to understand some basic `Go` language knowledge before proceeding to the next step.
New to Go? We recommend checking out our [Environment Setup Guide](../../docs/其他资料/准备工作/准备工作.md) first to get your development environment ready.

If you encounter any problems in any chapter of the quick start, feel free to leave a comment 💬, and we will try our best to provide you with an answer as soon as possible 🌟🌟.
Stuck or have questions? Feel free to leave a comment 💬. Our community is here to help, and we'll get back to you as quickly as possible 🌟🌟.
:::

## Limitations
## Go Version Requirements

To ensure the stability and security of the framework, the minimum required base version of the `Go` language for the `GoFrame` framework is usually 1 to 3 versions lower than the latest `Go` language version.
To ensure stability and security, `GoFrame` maintains compatibility with recent Go versions. We typically support the latest release and three previous versions.

Minimum `Go` version required by the current latest framework version:
Minimum requirement:
```bash
golang version >= 1.20
```

## Installation
You can install the latest version of the framework in the following way:
## Getting Started

Install the latest version:
```bash
go get -u -v github.com/gogf/gf/v2
```

Typically, include and use the latest version of `GoFrame` in the project's `go.mod`:

Or add this to your `go.mod`:
```bash
require github.com/gogf/gf/v2 latest
```

## Running
## Quick Test

Let's try running the following code:
Let's verify your installation with a simple program:
```go title="main.go"
package main

Expand All @@ -54,15 +54,15 @@ func main() {
fmt.Println("Hello GF:", gf.VERSION)
}
```
This simple code example prints the currently introduced `GoFrame` framework version. Execute it with the following command:

Run it:
```bash
go run main.go
```
You will see in the terminal:

You should see something like:
```bash
Hello GF: v2.7.4
```

Congratulations! This means you have successfully referenced `GoFrame` in the current project.

Next, we will use `GoFrame` to develop a simple `HTTP Server` service.
Perfect! Now that `GoFrame` is set up, let's build your first HTTP server.
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,30 @@ keywords: [GoFrame, Middleware, Web Server, ErrorHandler, Request Interception,
description: "Use middleware in the GoFrame framework to intercept requests and return results, and implement custom processing logic through pre and post middleware. The example code demonstrates how to define an error handling middleware and bind it to a route. Middleware makes request error handling and output format unification flexible and powerful."
---

To address the question left over from the previous chapter: how to capture the returned error object and perform custom error handling. In this chapter, we will briefly introduce the middleware feature of the `Web Server` and then answer this question.
Remember the question from our previous chapter about handling error objects? Let's solve it by exploring the `Web Server`'s middleware feature.

## Introduction to Middleware
## Understanding Middleware

Middleware is an interceptor design that can intercept requests and return results in a `Web Server`, and perform custom processing logic before and after them.
Middleware acts as an interceptor in your web server, allowing you to process requests both before and after they reach your route handlers. You can use middleware to modify requests, validate data, handle errors, or transform responses.

The definition of middleware is the same as a normal route callback function, but you can use the `Middleware` attribute object in the `Request` parameter to control the request flow.

There are two types of middleware: **Pre-middleware** and **Post-middleware**. Pre-middleware is called before the route service function, post-middleware is called after it.
Middleware functions look similar to regular route handlers but include a special `Middleware` object for controlling request flow. There are two types:
- **Pre-middleware**: Executes before the route handler
- **Post-middleware**: Executes after the route handler

Here's the basic structure:
```go
func Middleware(r *ghttp.Request) {
// Pre-middleware processing logic
// Pre-middleware logic
r.Middleware.Next()
// Post-middleware processing logic
// Post-middleware logic
}
```

After executing the processing logic in the middleware, the `r.Middleware.Next()` method is used to further execute the next process; if you exit directly without calling the `r.Middleware.Next()` method at this point, the subsequent execution process will be exited (for example, it can be used for request authentication processing).
The `r.Middleware.Next()` call passes control to the next handler in the chain. If you skip this call, the chain stops and returns immediately (useful for authentication middleware that needs to block unauthorized requests).

## Using Middleware
## Implementing Error Handling

We use middleware to make a simple modification to the program from the previous chapter, as follows:
Let's enhance our previous example with middleware:

```go title="main.go"
package main
Expand All @@ -43,8 +44,8 @@ import (

type HelloReq struct {
g.Meta `path:"/" method:"get"`
Name string `v:"required" dc:"Name"`
Age int `v:"required" dc:"Age"`
Name string `v:"required" dc:"User's name"`
Age int `v:"required" dc:"User's age"`
}
type HelloRes struct{}

Expand All @@ -61,11 +62,10 @@ func (Hello) Say(ctx context.Context, req *HelloReq) (res *HelloRes, err error)
}

func ErrorHandler(r *ghttp.Request) {
// Execute the route callback function
r.Middleware.Next()
// Check if an error has occurred

if err := r.GetError(); err != nil {
r.Response.Write("error occurs: ", err.Error())
r.Response.Write("Error: ", err.Error())
return
}
}
Expand All @@ -83,12 +83,13 @@ func main() {
}
```

- We have defined an error-handling middleware `ErrorHandler`. In this middleware, we first execute the route function flow through `r.Middleware.Next()`, and then obtain whether an error has occurred in the route callback function through `r.GetError()`. If an error occurs, the error message is directly displayed.
- In the route registration, we bind the error handling middleware to all registered routes under this route group through `group.Middleware(ErrorHandler)`.
Key changes:
- We've added an `ErrorHandler` middleware that checks for errors after the route handler executes
- The middleware is applied to all routes in the group via `group.Middleware(ErrorHandler)`

## Execution Result
## Testing the Changes

After running, the terminal outputs:
When you run the server, you'll see:

```text
2024-11-06 22:30:06.927 [INFO] pid[35434]: http server started listening on [:8000]
Expand All @@ -100,18 +101,18 @@ After running, the terminal outputs:
----------|--------|-------|-------------------|--------------------
```

The `MIDDLEWARE` section here has an additional `main.ErrorHandler` method, indicating the name of the middleware bound to this route.
Notice that our `ErrorHandler` is now listed in the middleware column.

We access http://127.0.0.1:8000/?name=john&age=18 and can see that the page output matches the expectation.
Let's test with valid parameters at http://127.0.0.1:8000/?name=john&age=18:

![img.png](img.png)

We try an invalid parameter request http://127.0.0.1:8000/ and can see that the page output also matches the expectation.
And with missing parameters at http://127.0.0.1:8000/:

![img_4.png](img_4.png)

## Learning Summary
## Looking Ahead

We used middleware to perform custom handling of request errors and capture validation errors to return custom error messages. As you can see, the functionality of middleware is very flexible and powerful, and of course not limited to handling small scenarios like validation errors.
We've seen how middleware can elegantly handle error cases and customize error messages. But this is just scratching the surface of what middleware can do.

Imagine, if there are many APIs in our project, and the output formats of these APIs are usually fixed, such as all in `json` format. Can we unify the return data structure directly through middleware? The answer is, of course, yes, which we will introduce in the next chapter.
Consider a common scenario: most APIs in a project typically return responses in a consistent format (like JSON). Could we use middleware to standardize this across all our endpoints? Absolutely! That's exactly what we'll explore in the next chapter.
Loading

0 comments on commit bd4dd74

Please sign in to comment.