2
2
extern crate diesel;
3
3
4
4
use std:: env;
5
- use std:: error:: Error ;
6
5
use std:: sync:: Mutex ;
7
6
8
7
use log:: debug;
@@ -11,25 +10,19 @@ use log::info;
11
10
use log:: trace;
12
11
use log:: warn;
13
12
14
- use diesel:: expression:: AsExpression ;
15
13
use diesel:: prelude:: * ;
16
- use diesel:: query_builder:: AsQuery ;
17
14
use diesel:: MysqlConnection ;
18
15
19
- use rouille:: router;
20
-
21
- use serde;
22
- use serde_json;
23
-
24
16
use dotenv:: dotenv;
25
17
26
18
use self :: errors:: WebdevError ;
27
19
use self :: errors:: WebdevErrorKind ;
28
- use self :: schema:: users;
29
20
30
21
mod errors;
31
- mod models;
32
- mod schema;
22
+ mod users;
23
+
24
+ use self :: users:: models:: UserRequest ;
25
+ use self :: users:: requests:: handle_user;
33
26
34
27
fn main ( ) {
35
28
dotenv ( ) . ok ( ) ;
@@ -44,7 +37,7 @@ fn main() {
44
37
Err ( e) => {
45
38
error ! ( "Could not read DATABASE_URL environment variable" ) ;
46
39
return ;
47
- } ,
40
+ }
48
41
} ;
49
42
50
43
debug ! ( "Connecting to {}" , database_url) ;
@@ -75,7 +68,7 @@ fn main() {
75
68
rouille:: Response :: text ( "" )
76
69
. with_additional_header (
77
70
"Access-Control-Allow-Methods" ,
78
- "POST, GET, DELETE, OPTIONS"
71
+ "POST, GET, DELETE, OPTIONS" ,
79
72
)
80
73
. with_additional_header ( "Access-Control-Allow-Origin" , "*" )
81
74
. with_additional_header ( "Access-Control-Allow-Headers" , "X-PINGOTHER, Content-Type" )
@@ -91,140 +84,24 @@ fn main() {
91
84
92
85
let response = handle_request ( request, & current_connection) ;
93
86
94
- let http_response = match response {
95
- Ok ( user_response) => {
96
- match user_response {
97
- models:: UserResponse :: OneUser ( user) => rouille:: Response :: json ( & user) ,
98
- models:: UserResponse :: ManyUsers ( users) => rouille:: Response :: json ( & users) ,
99
- models:: UserResponse :: NoResponse => rouille:: Response :: empty_204 ( ) ,
100
- }
101
- }
102
- Err ( e) => {
103
- if let Some ( err_source) = e. source ( ) {
104
- error ! ( "Error processing request: {}" , err_source) ;
105
- } else {
106
- error ! ( "Error processing request" ) ;
107
- }
108
-
109
- rouille:: Response :: from ( e)
110
- }
111
- } ;
112
-
113
- http_response. with_additional_header ( "Access-Control-Allow-Origin" , "*" )
87
+ response. with_additional_header ( "Access-Control-Allow-Origin" , "*" )
114
88
}
115
89
} ) ;
116
90
}
117
91
118
92
fn handle_request (
119
93
request : & rouille:: Request ,
120
94
database_connection : & MysqlConnection ,
121
- ) -> Result < models:: UserResponse , WebdevError > {
122
- router ! ( request,
123
- ( GET ) ( /users) => {
124
- // NOTE: get_param does a right search, so any param that is the same as the end of
125
- // another param will be treated as the same. That is why '_exact' is at the end
126
- // See rouille lib.rs, line 694 (fn get_param in impl Request).
127
- // TODO: Find a way around this?
128
- handle_get(
129
- request. get_param( "first_name_exact" ) ,
130
- request. get_param( "last_name_exact" ) ,
131
- if let Some ( p) = request. get_param( "banner_id_exact" ) { Some ( p. parse( ) ?) } else { None } ,
132
- if let Some ( p) = request. get_param( "has_email" ) { Some ( p. parse( ) ?) } else { None } ,
133
- request. get_param( "email_exact" ) ,
134
- database_connection
135
- ) . map( |s| models:: UserResponse :: ManyUsers ( s) )
136
- } ,
137
- ( POST ) ( /users) => {
138
- let request_body = request. data( ) . ok_or( WebdevError :: new( WebdevErrorKind :: Format ) ) ?;
139
- let new_user: models:: NewUser = serde_json:: from_reader( request_body) ?;
140
-
141
- handle_insert( new_user, database_connection) . map( |s| models:: UserResponse :: OneUser ( s) )
142
- } ,
143
- ( POST ) ( /users/{ id: u64 } ) => {
144
- let request_body = request. data( ) . ok_or( WebdevError :: new( WebdevErrorKind :: Format ) ) ?;
145
- let update_user: models:: PartialUser = serde_json:: from_reader( request_body) ?;
146
- handle_update( id, update_user, database_connection) . map( |_| models:: UserResponse :: NoResponse )
147
- } ,
148
- ( DELETE ) ( /users/{ id: u64 } ) => {
149
- handle_delete( id, database_connection) . map( |_| models:: UserResponse :: NoResponse )
150
- } ,
151
- _ => Err ( WebdevError :: new( WebdevErrorKind :: NotFound ) )
152
- )
153
- }
154
-
155
- fn handle_get (
156
- first_name_filter : Option < String > ,
157
- last_name_filter : Option < String > ,
158
- banner_id_filter : Option < u32 > ,
159
- has_email_filter : Option < bool > ,
160
- email_filter : Option < String > ,
161
- database_connection : & MysqlConnection ,
162
- ) -> Result < models:: UserList , WebdevError > {
163
- let mut users_query = users:: table. as_query ( ) . into_boxed ( ) ;
164
-
165
- if let Some ( p) = first_name_filter {
166
- users_query = users_query. filter ( users:: first_name. eq ( p) ) ;
167
- }
168
-
169
- if let Some ( p) = last_name_filter {
170
- users_query = users_query. filter ( users:: last_name. eq ( p) ) ;
171
- }
172
-
173
- if let Some ( p) = banner_id_filter {
174
- users_query = users_query. filter ( users:: banner_id. eq ( p) ) ;
175
- }
176
-
177
- if let Some ( p) = has_email_filter {
178
- if p {
179
- trace ! ( "Not null!" ) ;
180
- users_query = users_query. filter ( users:: email. is_not_null ( ) ) ;
181
- } else {
182
- trace ! ( "Null!" ) ;
183
- users_query = users_query. filter ( users:: email. is_null ( ) ) ;
95
+ ) -> rouille:: Response {
96
+ if let Some ( user_request) = request. remove_prefix ( "/users" ) {
97
+ match UserRequest :: from_rouille ( & user_request) {
98
+ Err ( err) => rouille:: Response :: from ( err) ,
99
+ Ok ( user_request) => match handle_user ( user_request, database_connection) {
100
+ Ok ( user_response) => user_response. to_rouille ( ) ,
101
+ Err ( err) => rouille:: Response :: from ( err) ,
102
+ } ,
184
103
}
104
+ } else {
105
+ rouille:: Response :: empty_404 ( )
185
106
}
186
-
187
- if let Some ( p) = email_filter {
188
- users_query = users_query. filter ( users:: email. eq ( p) ) ;
189
- }
190
-
191
- trace ! ( "Executing query: {}" , diesel:: debug_query( & users_query) ) ;
192
-
193
- let all_users = users_query. load :: < models:: User > ( database_connection) ?;
194
- let user_list = models:: UserList {
195
- users : all_users
196
- } ;
197
-
198
- Ok ( user_list)
199
- }
200
-
201
- fn handle_insert (
202
- new_user : models:: NewUser ,
203
- database_connection : & MysqlConnection ,
204
- ) -> Result < models:: User , WebdevError > {
205
-
206
- diesel:: insert_into ( users:: table)
207
- . values ( new_user)
208
- . execute ( database_connection) ?;
209
-
210
- let mut inserted_users = users:: table
211
- . filter ( diesel:: dsl:: sql ( "id = LAST_INSERT_ID()" ) )
212
- . load :: < models:: User > ( database_connection) ?;
213
-
214
- match inserted_users. pop ( ) {
215
- Some ( user) => Ok ( user) ,
216
- None => Err ( WebdevError :: new ( WebdevErrorKind :: Database ) ) ,
217
- }
218
- }
219
-
220
- fn handle_update ( id : u64 , user : models:: PartialUser , database_connection : & MysqlConnection ) -> Result < ( ) , WebdevError > {
221
- diesel:: update ( users:: table) . filter ( users:: id. eq ( id) ) . set ( & user) . execute ( database_connection) ?;
222
-
223
- Ok ( ( ) )
224
- }
225
-
226
- fn handle_delete ( id : u64 , database_connection : & MysqlConnection ) -> Result < ( ) , WebdevError > {
227
- diesel:: delete ( users:: table. filter ( users:: id. eq ( id) ) ) . execute ( database_connection) ?;
228
-
229
- Ok ( ( ) )
230
107
}
0 commit comments