Skip to content

Commit 5f29322

Browse files
migrated code into different files
1 parent 45600b0 commit 5f29322

File tree

7 files changed

+188
-158
lines changed

7 files changed

+188
-158
lines changed

example/simple_get.f90

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
program simple_get
2-
use http_client, only : response_type, http_request, HTTP_GET
2+
use http, only : response_type, request
33
implicit none
44
type(response_type) :: response
55

6-
response = http_request(url='https://jsonplaceholder.typicode.com/todos/1', method=HTTP_GET)
6+
response = request(url='https://jsonplaceholder.typicode.com/todos/1')
77
print *, "Response Code : ", response%status_code
88
print *, "Response Length : ", response%content_length
9+
print *, "Response Method : ", response%method
910
print *, "Response Content : ", response%content
1011

1112
end program simple_get

fpm.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name = "http-client"
1+
name = "http"
22
version = "0.1.0"
33
license = "MIT"
44
author = "Fortran-lang"

src/http-client.f90

Lines changed: 0 additions & 155 deletions
This file was deleted.

src/http.f90

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module http
2+
use http_request, only : HTTP_DELETE, HTTP_GET, HTTP_HEAD, HTTP_PATCH, HTTP_POST, HTTP_POST
3+
use http_response, only : response_type
4+
use http_server, only : request
5+
end module http

src/http/http_request.f90

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module http_request
2+
implicit none
3+
private
4+
! HTTP methods:
5+
integer, parameter, public :: HTTP_GET = 1
6+
integer, parameter, public :: HTTP_HEAD = 2
7+
integer, parameter, public :: HTTP_POST = 3
8+
integer, parameter, public :: HTTP_PUT = 4
9+
integer, parameter, public :: HTTP_DELETE = 5
10+
integer, parameter, public :: HTTP_PATCH = 6
11+
! Request Type
12+
type, public :: request_type
13+
character(len=:), allocatable :: url
14+
integer :: method
15+
end type request_type
16+
17+
end module http_request

src/http/http_response.f90

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module http_response
2+
use, intrinsic :: iso_c_binding, only : c_size_t
3+
implicit none
4+
! Response Type
5+
type, public :: response_type
6+
character(len=:), allocatable :: content
7+
character(len=:), allocatable :: url
8+
character(len=:), allocatable :: method
9+
integer :: status_code = 0
10+
integer(kind=c_size_t) :: content_length = 0
11+
end type response_type
12+
contains
13+
14+
end module http_response

src/http/http_server.f90

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
module http_server
2+
use iso_c_binding
3+
use curl
4+
use http_request, only : request_type
5+
use http_response, only : response_type
6+
7+
implicit none
8+
9+
! http_server Type
10+
type :: client_type
11+
type(request_type) :: request
12+
type(c_ptr) :: curl_ptr
13+
contains
14+
procedure :: client_get_response
15+
procedure :: client_set_method
16+
end type client_type
17+
18+
interface client_type
19+
module procedure new_client
20+
end interface client_type
21+
22+
interface request
23+
module procedure new_request
24+
end interface request
25+
26+
public :: request
27+
28+
29+
contains
30+
! Constructor for request_type type.
31+
function new_request(url, method) result(response)
32+
character(len=*) :: url
33+
integer, optional :: method
34+
type(request_type) :: request
35+
type(response_type) :: response
36+
type(client_type) :: client
37+
38+
if(present(method)) then
39+
request%method = method
40+
else
41+
request%method = 1
42+
end if
43+
request%url = url
44+
client = client_type(request=request)
45+
response = client%client_get_response()
46+
47+
end function new_request
48+
! Constructor for client_type type.
49+
function new_client(request) result(client)
50+
type(client_type) :: client
51+
type(request_type) :: request
52+
53+
client%request = request
54+
end function new_client
55+
56+
function client_get_response(this) result(response)
57+
class(client_type) :: this
58+
type(response_type), target :: response
59+
integer :: rc
60+
! logic for populating response using fortran-curl
61+
response%url = this%request%url
62+
! response%method = this%request%method
63+
64+
this%curl_ptr = curl_easy_init()
65+
66+
if (.not. c_associated(this%curl_ptr)) then
67+
stop 'Error: curl_easy_init() failed'
68+
end if
69+
! setting request URL
70+
rc = curl_easy_setopt(this%curl_ptr, CURLOPT_URL, this%request%url // c_null_char)
71+
! setting request method
72+
rc = this%client_set_method(response)
73+
! setting callback for writing received data
74+
rc = curl_easy_setopt(this%curl_ptr, CURLOPT_WRITEFUNCTION, c_funloc(client_response_callback))
75+
! setting response pointer to write callback
76+
rc = curl_easy_setopt(this%curl_ptr, CURLOPT_WRITEDATA, c_loc(response))
77+
78+
! Send request.
79+
rc = curl_easy_perform(this%curl_ptr)
80+
81+
if (rc /= CURLE_OK) then
82+
print '(a)', 'Error: curl_easy_perform() failed'
83+
stop
84+
end if
85+
! setting response status_code
86+
rc = curl_easy_getinfo(this%curl_ptr, CURLINFO_RESPONSE_CODE, response%status_code)
87+
call curl_easy_cleanup(this%curl_ptr)
88+
89+
end function client_get_response
90+
91+
function client_set_method(this, response) result(status)
92+
class(client_type) :: this
93+
type(response_type), intent(out) :: response
94+
integer :: status
95+
96+
select case(this%request%method)
97+
case(1)
98+
status = curl_easy_setopt(this%curl_ptr, CURLOPT_CUSTOMREQUEST, 'GET' // c_null_char)
99+
response%method = 'GET'
100+
case(2)
101+
status = curl_easy_setopt(this%curl_ptr, CURLOPT_CUSTOMREQUEST, 'HEAD' // c_null_char)
102+
response%method = 'HEAD'
103+
case(3)
104+
status = curl_easy_setopt(this%curl_ptr, CURLOPT_CUSTOMREQUEST, 'POST' // c_null_char)
105+
response%method = 'POST'
106+
case(4)
107+
status = curl_easy_setopt(this%curl_ptr, CURLOPT_CUSTOMREQUEST, 'PUT' // c_null_char)
108+
response%method = 'PUT'
109+
case(5)
110+
status = curl_easy_setopt(this%curl_ptr, CURLOPT_CUSTOMREQUEST, 'DELETE' // c_null_char)
111+
response%method = 'DELETE'
112+
case(6)
113+
status = curl_easy_setopt(this%curl_ptr, CURLOPT_CUSTOMREQUEST, 'PATCH' // c_null_char)
114+
response%method = 'PATCH'
115+
end select
116+
end function client_set_method
117+
118+
function client_response_callback(ptr, size, nmemb, client_data) bind(c)
119+
type(c_ptr), intent(in), value :: ptr
120+
integer(kind=c_size_t), intent(in), value :: size
121+
integer(kind=c_size_t), intent(in), value :: nmemb
122+
type(c_ptr), intent(in), value :: client_data
123+
integer(kind=c_size_t) :: client_response_callback
124+
type(response_type), pointer :: response
125+
character(len=:), allocatable :: buf
126+
127+
client_response_callback = int(0, kind=c_size_t)
128+
129+
! Are the passed C pointers associated?
130+
if (.not. c_associated(ptr)) return
131+
if (.not. c_associated(client_data)) return
132+
133+
! Convert C pointer to Fortran pointer.
134+
call c_f_pointer(client_data, response)
135+
if (.not. allocated(response%content)) response%content = ''
136+
137+
! Convert C pointer to Fortran allocatable character.
138+
call c_f_str_ptr(ptr, buf, nmemb)
139+
if (.not. allocated(buf)) return
140+
response%content = response%content // buf
141+
deallocate (buf)
142+
response%content_length = response%content_length + nmemb
143+
! Return number of received bytes.
144+
client_response_callback = nmemb
145+
end function client_response_callback
146+
147+
148+
end module http_server

0 commit comments

Comments
 (0)