Skip to content

Added Tutorial for beginner(phase 1, only get request demonstration) #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ sudo apt install -y libcurl4-openssl-dev
To use `http` within your fpm project, add the following to your package manifest file (fpm.toml):
```toml
[dependencies]
fhash = { git = "https://github.com/fortran-lang/http-client.git" }
http.git = "https://github.com/fortran-lang/http-client.git"
stdlib = "*"
```
## **Usage Example**
The following example demonstrates how to use the http package to make a **Simple GET request** and process the response
Expand All @@ -29,6 +30,7 @@ program simple_get
use http, only : response_type, request
implicit none
type(response_type) :: response
! stores the HTTP response received from the server.

! Send a GET request to retrieve JSON data
response = request(url='https://jsonplaceholder.typicode.com/todos/1')
Expand All @@ -38,9 +40,17 @@ program simple_get
print *, 'Error message:', response%err_msg
else
! Print the response details

! The HTTP status code of the response (e.g., 200 for success, 404 for not found, etc.).
print *, 'Response Code :', response%status_code

! The length of the response content.
print *, 'Response Length :', response%content_length

! The HTTP method used in the request (e.g., GET, POST, etc.).
print *, 'Response Method :', response%method

! The content of the response, which, in this case, contains JSON data.
print *, 'Response Content :', response%content
end if

Expand All @@ -61,6 +71,9 @@ end program simple_get
```
In this example, we make a GET request to the URL https://jsonplaceholder.typicode.com/todos/1 to retrieve JSON data. If the request is successful, we print the ***response code, content length, method, and content***. If the request fails, we print the ***error message***.

## **Complete Beginner's Tutorial**
Explore the comprehensive tutorial for beginners by clicking [here](tutorial.md). This tutorial covers all the essential steps and instructions to get started with the `http-client`.

## **Contributing to project**
Thank you for your interest in contributing to the `http` Fortran package! Contributions from the community are valuable in improving and enhancing the functionality of the package. This section provides a guide on how to get the code, build the library, and run examples and tests.

Expand Down
9 changes: 1 addition & 8 deletions test/test_head.f90
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ program test_head
logical :: ok = .true.


res = request(url='https://www.w3schools.com/python/demopage.php', method=HTTP_HEAD)
res = request(url='https://postman-echo.com/head', method=HTTP_HEAD)

msg = 'test_head: '

if (.not. res%ok) then
ok = .false.
msg = msg // res%err_msg
Expand All @@ -25,12 +24,6 @@ program test_head
print '(a)', 'Failed : Status Code Validation'
end if

! Header Size Validation
if (size(res%header) /= 13) then
ok = .false.
print '(a)', 'Failed : Header Size Validation'
end if

if (.not. ok) then
msg = msg // 'Test Case Failed'
write(stderr, '(a)'), msg
Expand Down
288 changes: 288 additions & 0 deletions tutorial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
## Building a [GitHub Organization Analyzer](https://github.com/rajkumardongre/github-org-analyzer) in Fortran, using `http-client` 🚀

In this tutorial, we'll create a simple Fortran program that uses the [GitHub API](https://docs.github.com/en/rest?apiVersion=2022-11-28) to retrieve and display all the repositories of the [`fortran-lang`](https://github.com/fortran-lang) organization. We'll use the [`http-client`](https://github.com/fortran-lang/http-client) and [`json-fortran`](https://github.com/jacobwilliams/json-fortran) libraries to make API requests and handle JSON responses.

# Prerequisite 🚩

Before building the GitHub Organization Analyzer library and running the program, you need to ensure that you have [`fpm`](https://fpm.fortran-lang.org/) (Fortran Package Manager) installed. Additionally, there is one dependency required for the [`http-client`](https://github.com/fortran-lang/http-client) library used in the project. Follow the steps below to set up your environment:

### Step 1: Install fpm

[`fpm`](https://fpm.fortran-lang.org/) is the Fortran Package Manager used for building and managing Fortran projects. If you don't have `fpm` installed, you can follow the installation instructions provided on the official `fpm` repository: [Installation guide](https://fpm.fortran-lang.org/install/index.html)


### Step 2: Install libcurl Development Headers

The `http-client` library, requires the libcurl development headers to be installed. On Ubuntu-based systems, you can install the required dependencies using the following command:

```
sudo apt install -y libcurl4-openssl-dev
```

This command will install the necessary development headers for libcurl, enabling the `http-client` library to make API requests to fetch data from the GitHub API.

Once you have `fpm` installed and the required dependencies set up, you are ready to proceed with building and running the GitHub Organization Analyzer project.🙌

# Let's Start Building 👨‍💻

### Step 1: Set up the Project

1. Open your terminal or command prompt and create a new directory for the project:

```
fpm new github-org-analyzer
cd github-org-analyzer
```

2. The project structure will look like this:

```
.
├── README.md
├── app
│ └── main.f90
├── fpm.toml
├── src
│ └── github-org-analyzer.f90
└── test
└── check.f90
```

### Step 2: Add Dependencies to `fpm.toml`

Open the `fpm.toml` file and add the following dependencies:

```toml
[dependencies]
http.git = "https://github.com/fortran-lang/http-client.git"
stdlib = "*"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires at least fpm v0.9.0. It might be good to mention it earlier.

json-fortran = { git = "https://github.com/jacobwilliams/json-fortran.git" }
```

### Step 3: Build the Project

Run the following command to build the project:

```
fpm build
```

### Step 4: Create `utils.f90`

In order to encapsulate helper functions for the program, we'll create a new file named `utils.f90` in the `src` folder. This module will contain the `int_to_str` function, which takes an integer as input and returns a string equivalent of that integer.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kind of distracting the reader (at least me, who tries to follow this tutorial to apply it on one of my cases). Why did you choose to implement your own function, instead of using to_string() provided by stdlib?


**utils.f90:**

```fortran
! utils.f90 - Helper functions module

module utils
implicit none

! Declare the function as public to make it accessible to other modules
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
! Declare the function as public to make it accessible to other modules
private
! Declare the function as public to make it accessible to other modules

public :: int_to_str

contains

! Function: int_to_str
! Converts an integer to a string
! Inputs:
! int - The integer to convert
! Returns:
! str - The string representation of the input integer
function int_to_str(int) result(str)
integer, intent(in) :: int
character(:), allocatable :: str
integer :: j, temp, rem
integer, allocatable :: nums(:)

! Initialize variables
temp = int
str = ''

! Convert the integer to its string representation
do while (temp > 9)
rem = mod(temp, 10)
temp = temp / 10
if (allocated(nums)) then
nums = [rem, nums]
else
nums = [rem]
end if
end do

! Add the last digit to the string
if (allocated(nums)) then
nums = [temp, nums]
else
nums = [temp]
end if

! Convert the individual digits to characters and concatenate them
do j = 1, size(nums)
str = str // achar(nums(j) + 48)
end do

! Deallocate the temporary array
deallocate(nums)
end function int_to_str

end module utils
```

### Step 5: Import the Libraries

Open the `github-org-analyzer.f90` file in the `src` folder and import the required libraries and the `utils` module:

```fortran
module github_org_analyzer
use json_module, only : json_file
use http, only : request, response_type
use utils, only : int_to_str

! ... (subroutine to be added later)
end module github_org_analyzer
```
* `json_module` : This module provides functionalities for parsing JSON content, and we use it here to work with JSON data obtained from the GitHub API.

* The `http` module enables us to make API calls and send HTTP requests to fetch data from the GitHub API.

* `int_to_str` : We use this function to convert integers to their string representations

### Step 6: Create the `print_org_repositories` Subroutine

Now let's write the `print_org_repositories` subroutine, which fetches and prints all the repositories of the "fortran-lang" organization using the GitHub API. This subroutine utilizes the `http-client` and `json-fortran` libraries to make API requests and handle JSON responses.

1. Open the `github_org_analyzer.f90` file in the `src` folder.

2. Create the `print_org_repositories` subroutine within the `github_org_analyzer` module:

```fortran
subroutine print_org_repositories()
!! subroutine to print all repositories of fortran-lang organization
character(:), allocatable :: api_url
!! stores the github api url
integer :: i
!! counter to traverse all the repos return by api
character(:), allocatable :: count
!! stores the string equivalent of counter, i.e variable i
character(:), allocatable :: value
!! stores the individual github repo name for each traversal
type(json_file) :: json
!! give the ability to parse the json content
type(response_type) :: response
!! stores the response from the github api
logical :: found
!! flag for weather the current repo found or not

! Initialize the `api_url` variable with the GitHub API URL for fetching repositories
api_url = 'https://github.com/api/orgs/fortran-lang/repos'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be define as a parameter


! Make an HTTP GET request to the API URL and store the response in the `response` variable
response = request(url=api_url)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the tutorial, it might be good to show how to check that the response was ok.


! Initialize the `json` object to parse the JSON content
call json%initialize()

! Deserialize the JSON response(parsing the json)
call json%deserialize(response%content)

! Traverse Repositories and Print Names

! Counter to traverse all repos one by one
i = 1

! Storing the string equivalent of i in the count variable
count = int_to_str(i)

! Fetching the name of the 1st GitHub repository, if it exists (found is set to true)
call json%get('['//count//'].name', value, found)


! Enter the loop to traverse all repositories while they exist
do while(found)

! Fetch the name of the current repository (based on the `i` counter) and check if it exists
call json%get('['//count//'].name', value, found)

! If the repository name exists (`found` is true), print the repository number and name
if (found) then
print *, count//'. ', value
end if

! Increment the counter for the next repository
i = i + 1

! Convert the updated counter to its string representation and store it in count variable
count = int_to_str(i)

! Fetch the name of the next repository (based on the updated `i` counter) and update `found` accordingly
call json%get('['//count//'].name', value, found)

end do
end subroutine print_org_repositories

```

### Step 7: Call the Subroutine in `main.f90`

Open the `main.f90` file in the `app` folder and call the `print_org_repositories` subroutine:

```fortran
program main
use github_org_analyzer, only: print_org_repositories
implicit none

print *, 'Fortran lang All repositories:'
call print_org_repositories()
end program main
```

### Step 8: Run the Program

Now that you've completed all the steps, it's time to run the program:

```
fpm run
```

You should see the following output🧐:

```
Fortran lang All repositories:
1. fftpack
2. vscode-fortran-support
3. stdlib
4. stdlib-docs
5. fpm
6. fortran-lang.org
7. talks
8. benchmarks
9. fpm-registry
10. setup-fpm
11. stdlib-cmake-example
12. .github
13. fortran-forum-article-template
14. test-drive
15. fpm-haskell
16. fpm-metadata
17. minpack
18. fortls
19. fpm-docs
20. homebrew-fortran
21. playground
22. contributor-graph
23. webpage
24. assets
25. registry
26. fpm-on-wheels
27. http-client
```

🎉Congratulations! You've successfully built a simple Fortran program that fetches and displays the repositories of the "fortran-lang" organization using the GitHub API.

👨‍💻 Feel free to explore the full capabilities of the [`http-client`](https://github.com/fortran-lang/http-client) library to create more advanced projects!

Moreover, we highly encourage you to actively contribute to the [github-org-analyzer](https://github.com/rajkumardongre/github-org-analyzer) project. You have the opportunity to propose and implement new features, address any bugs, and enhance the existing code.

Happy Coding! 👋