@@ -50,110 +50,130 @@ module AiohttpWebModel {
50
50
result = applicationInstance ( ) .getMember ( "router" )
51
51
}
52
52
53
- /** A route setup in `aiohttp.web` */
54
- abstract class AiohttpRouteSetup extends HTTP:: Server:: RouteSetup:: Range {
53
+ /**
54
+ * A route setup in `aiohttp.web`. Since all route-setups can technically use either
55
+ * coroutines or view-classes as the handler argument (although that's not how you're
56
+ * **supposed** to do things), we also need to handle this.
57
+ *
58
+ * Extend this class to refine existing API models. If you want to model new APIs,
59
+ * extend `AiohttpRouteSetup::Range` instead.
60
+ */
61
+ class AiohttpRouteSetup extends HTTP:: Server:: RouteSetup:: Range {
62
+ AiohttpRouteSetup:: Range range ;
63
+
64
+ AiohttpRouteSetup ( ) { this = range }
65
+
55
66
override Parameter getARoutedParameter ( ) { none ( ) }
56
67
57
68
override string getFramework ( ) { result = "aiohttp.web" }
58
- }
59
-
60
- /** An aiohttp route setup that uses coroutines (async function) as request handler. */
61
- abstract class AiohttpCoroutineRouteSetup extends AiohttpRouteSetup {
62
- /** Gets the argument specifying the request handler (which is a coroutine/async function) */
63
- abstract DataFlow:: Node getRequestHandlerArg ( ) ;
64
69
65
- override Function getARequestHandler ( ) {
66
- this .getRequestHandlerArg ( ) = poorMansFunctionTracker ( result )
67
- }
68
- }
70
+ /** Gets the argument specifying the handler (either a coroutine or a view-class). */
71
+ DataFlow:: Node getHandlerArg ( ) { result = range .getHandlerArg ( ) }
69
72
70
- /**
71
- * Gets a reference to a class, that has been backtracked from the view-class handler
72
- * argument `origin` (to a route-setup for view-classes).
73
- */
74
- private DataFlow:: LocalSourceNode viewClassBackTracker (
75
- DataFlow:: TypeBackTracker t , DataFlow:: Node origin
76
- ) {
77
- t .start ( ) and
78
- origin = any ( AiohttpViewRouteSetup rs ) .getViewClassArg ( ) and
79
- result = origin .getALocalSource ( )
80
- or
81
- exists ( DataFlow:: TypeBackTracker t2 |
82
- result = viewClassBackTracker ( t2 , origin ) .backtrack ( t2 , t )
83
- )
84
- }
73
+ override DataFlow:: Node getUrlPatternArg ( ) { result = range .getUrlPatternArg ( ) }
85
74
86
- /**
87
- * Gets a reference to a class, that has been backtracked from the view-class handler
88
- * argument `origin` (to a route-setup for view-classes).
89
- */
90
- DataFlow:: LocalSourceNode viewClassBackTracker ( DataFlow:: Node origin ) {
91
- result = viewClassBackTracker ( DataFlow:: TypeBackTracker:: end ( ) , origin )
92
- }
75
+ /** Gets the view-class that is referenced in the view-class handler argument, if any. */
76
+ Class getViewClass ( ) { result = range .getViewClass ( ) }
93
77
94
- Class getBackTrackedViewClass ( DataFlow:: Node origin ) {
95
- result .getParent ( ) = viewClassBackTracker ( origin ) .asExpr ( )
78
+ override Function getARequestHandler ( ) { result = range .getARequestHandler ( ) }
96
79
}
97
80
98
- /** An aiohttp route setup that uses view-classes as request handlers. */
99
- abstract class AiohttpViewRouteSetup extends AiohttpRouteSetup {
100
- /** Gets the argument specifying the view-class handler. */
101
- abstract DataFlow:: Node getViewClassArg ( ) ;
102
-
103
- /** Gets the view-class that is referenced in the view-class handler argument. */
104
- Class getViewClass ( ) { result = getBackTrackedViewClass ( this .getViewClassArg ( ) ) }
105
-
106
- override Function getARequestHandler ( ) {
107
- exists ( AiohttpViewClass cls |
108
- cls = this .getViewClass ( ) and
109
- result = cls .getARequestHandler ( )
110
- )
81
+ /** Provides a class for modeling new aiohttp.web route setups. */
82
+ private module AiohttpRouteSetup {
83
+ /**
84
+ * A route setup in `aiohttp.web`. Since all route-setups can technically use either
85
+ * coroutines or view-classes as the handler argument (although that's not how you're
86
+ * **supposed** to do things), we also need to handle this.
87
+ *
88
+ * Extend this class to model new APIs. If you want to refine existing API models,
89
+ * extend `AiohttpRouteSetup` instead.
90
+ */
91
+ abstract class Range extends DataFlow:: Node {
92
+ /** Gets the argument used to set the URL pattern. */
93
+ abstract DataFlow:: Node getUrlPatternArg ( ) ;
94
+
95
+ /** Gets the argument specifying the handler (either a coroutine or a view-class). */
96
+ abstract DataFlow:: Node getHandlerArg ( ) ;
97
+
98
+ /** Gets the view-class that is referenced in the view-class handler argument, if any. */
99
+ Class getViewClass ( ) { result = getBackTrackedViewClass ( this .getHandlerArg ( ) ) }
100
+
101
+ /**
102
+ * Gets a function that will handle incoming requests for this route, if any.
103
+ *
104
+ * NOTE: This will be modified in the near future to have a `RequestHandler` result, instead of a `Function`.
105
+ */
106
+ Function getARequestHandler ( ) {
107
+ this .getHandlerArg ( ) = poorMansFunctionTracker ( result )
108
+ or
109
+ exists ( AiohttpViewClass cls |
110
+ cls = this .getViewClass ( ) and
111
+ result = cls .getARequestHandler ( )
112
+ )
113
+ }
111
114
}
112
- }
113
115
114
- /**
115
- * A route-setup from `add_route` or any of `add_get`, `add_post`, etc. on an
116
- * `aiohttp.web.UrlDispatcher`.
117
- */
118
- class AiohttpUrlDispatcherAddRouteCall extends AiohttpCoroutineRouteSetup , DataFlow:: CallCfgNode {
119
- /** At what index route arguments starts, so we can handle "route" version together with get/post/... */
120
- int routeArgsStart ;
121
-
122
- AiohttpUrlDispatcherAddRouteCall ( ) {
123
- this = urlDispathcerInstance ( ) .getMember ( "add_" + HTTP:: httpVerbLower ( ) ) .getACall ( ) and
124
- routeArgsStart = 0
116
+ /**
117
+ * Gets a reference to a class, that has been backtracked from the view-class handler
118
+ * argument `origin` (to a route-setup for view-classes).
119
+ */
120
+ private DataFlow:: LocalSourceNode viewClassBackTracker (
121
+ DataFlow:: TypeBackTracker t , DataFlow:: Node origin
122
+ ) {
123
+ t .start ( ) and
124
+ origin = any ( Range rs ) .getHandlerArg ( ) and
125
+ result = origin .getALocalSource ( )
125
126
or
126
- this = urlDispathcerInstance ( ) .getMember ( "add_route" ) .getACall ( ) and
127
- routeArgsStart = 1
127
+ exists ( DataFlow:: TypeBackTracker t2 |
128
+ result = viewClassBackTracker ( t2 , origin ) .backtrack ( t2 , t )
129
+ )
128
130
}
129
131
130
- override DataFlow:: Node getUrlPatternArg ( ) {
131
- result in [ this .getArg ( routeArgsStart + 0 ) , this .getArgByName ( "path" ) ]
132
+ /**
133
+ * Gets a reference to a class, that has been backtracked from the view-class handler
134
+ * argument `origin` (to a route-setup for view-classes).
135
+ */
136
+ DataFlow:: LocalSourceNode viewClassBackTracker ( DataFlow:: Node origin ) {
137
+ result = viewClassBackTracker ( DataFlow:: TypeBackTracker:: end ( ) , origin )
132
138
}
133
139
134
- override DataFlow:: Node getRequestHandlerArg ( ) {
135
- result in [ this . getArg ( routeArgsStart + 1 ) , this . getArgByName ( "handler" ) ]
140
+ Class getBackTrackedViewClass ( DataFlow:: Node origin ) {
141
+ result . getParent ( ) = viewClassBackTracker ( origin ) . asExpr ( )
136
142
}
137
143
}
138
144
145
+ /** An aiohttp route setup that uses coroutines (async function) as request handler. */
146
+ class AiohttpCoroutineRouteSetup extends AiohttpRouteSetup {
147
+ AiohttpCoroutineRouteSetup ( ) { this .getHandlerArg ( ) = poorMansFunctionTracker ( _) }
148
+ }
149
+
150
+ /** An aiohttp route setup that uses view-classes as request handlers. */
151
+ class AiohttpViewRouteSetup extends AiohttpRouteSetup {
152
+ AiohttpViewRouteSetup ( ) { exists ( this .getViewClass ( ) ) }
153
+ }
154
+
139
155
/**
140
- * A route-setup from using `route` or any of `get`, `post`, etc. functions from `aiohttp.web`.
141
- *
142
- * Note that technically, this does not set up a route in itself (since it needs to be added to an application first).
143
- * However, modeling this way makes it easier, and we don't expect it to lead to many problems.
156
+ * A route-setup from
157
+ * - `add_route`, `add_view`, `add_get`, `add_post`, , etc. on an `aiohttp.web.UrlDispatcher`.
158
+ * - `route`, `view`, `get`, `post`, etc. functions from `aiohttp.web`.
144
159
*/
145
- class AiohttpWebRouteCall extends AiohttpCoroutineRouteSetup , DataFlow:: CallCfgNode {
160
+ class AiohttpAddRouteCall extends AiohttpRouteSetup :: Range , DataFlow:: CallCfgNode {
146
161
/** At what index route arguments starts, so we can handle "route" version together with get/post/... */
147
162
int routeArgsStart ;
148
163
149
- AiohttpWebRouteCall ( ) {
164
+ AiohttpAddRouteCall ( ) {
150
165
exists ( string funcName |
151
166
funcName = HTTP:: httpVerbLower ( ) and
152
167
routeArgsStart = 0
153
168
or
169
+ funcName = "view" and
170
+ routeArgsStart = 0
171
+ or
154
172
funcName = "route" and
155
173
routeArgsStart = 1
156
174
|
175
+ this = urlDispathcerInstance ( ) .getMember ( "add_" + funcName ) .getACall ( )
176
+ or
157
177
this = API:: moduleImport ( "aiohttp" ) .getMember ( "web" ) .getMember ( funcName ) .getACall ( )
158
178
)
159
179
}
@@ -162,21 +182,24 @@ module AiohttpWebModel {
162
182
result in [ this .getArg ( routeArgsStart + 0 ) , this .getArgByName ( "path" ) ]
163
183
}
164
184
165
- override DataFlow:: Node getRequestHandlerArg ( ) {
185
+ override DataFlow:: Node getHandlerArg ( ) {
166
186
result in [ this .getArg ( routeArgsStart + 1 ) , this .getArgByName ( "handler" ) ]
167
187
}
168
188
}
169
189
170
- /** A route-setup from using a `route` or any of `get`, `post`, etc. decorators from a `aiohttp.web.RouteTableDef`. */
171
- class AiohttpRouteTableDefRouteCall extends AiohttpCoroutineRouteSetup , DataFlow:: CallCfgNode {
190
+ /** A route-setup using a decorator, such as `route`, `view`, `get`, `post`, etc. on a `aiohttp.web.RouteTableDef`. */
191
+ class AiohttpDecoratorRouteSetup extends AiohttpRouteSetup :: Range , DataFlow:: CallCfgNode {
172
192
/** At what index route arguments starts, so we can handle "route" version together with get/post/... */
173
193
int routeArgsStart ;
174
194
175
- AiohttpRouteTableDefRouteCall ( ) {
195
+ AiohttpDecoratorRouteSetup ( ) {
176
196
exists ( string decoratorName |
177
197
decoratorName = HTTP:: httpVerbLower ( ) and
178
198
routeArgsStart = 0
179
199
or
200
+ decoratorName = "view" and
201
+ routeArgsStart = 0
202
+ or
180
203
decoratorName = "route" and
181
204
routeArgsStart = 1
182
205
|
@@ -194,63 +217,21 @@ module AiohttpWebModel {
194
217
result in [ this .getArg ( routeArgsStart + 0 ) , this .getArgByName ( "path" ) ]
195
218
}
196
219
197
- override DataFlow:: Node getRequestHandlerArg ( ) { none ( ) }
220
+ override DataFlow:: Node getHandlerArg ( ) { none ( ) }
198
221
199
- override Function getARequestHandler ( ) { result .getADecorator ( ) = this .asExpr ( ) }
200
- }
222
+ override Class getViewClass ( ) { result .getADecorator ( ) = this .asExpr ( ) }
201
223
202
- /**
203
- * A view-class route-setup from either:
204
- * - `add_view` method on a `aiohttp.web.UrlDispatcher`
205
- * - `view` function from `aiohttp.web`
206
- */
207
- class AiohttpViewRouteSetupFromFunction extends AiohttpViewRouteSetup , DataFlow:: CallCfgNode {
208
- AiohttpViewRouteSetupFromFunction ( ) {
209
- this = urlDispathcerInstance ( ) .getMember ( "add_view" ) .getACall ( )
210
- or
211
- this = API:: moduleImport ( "aiohttp" ) .getMember ( "web" ) .getMember ( "view" ) .getACall ( )
224
+ override Function getARequestHandler ( ) {
225
+ // we're decorating a class
226
+ exists ( this .getViewClass ( ) ) and
227
+ result = super .getARequestHandler ( )
212
228
or
213
- this =
214
- API:: moduleImport ( "aiohttp" )
215
- .getMember ( "web" )
216
- .getMember ( "RouteTableDef" )
217
- .getReturn ( )
218
- .getMember ( "view" )
219
- .getACall ( )
220
- }
221
-
222
- override DataFlow:: Node getUrlPatternArg ( ) {
223
- result in [ this .getArg ( 0 ) , this .getArgByName ( "path" ) ]
224
- }
225
-
226
- override DataFlow:: Node getViewClassArg ( ) {
227
- result in [ this .getArg ( 1 ) , this .getArgByName ( "handler" ) ]
229
+ // we're decorating a function
230
+ not exists ( this .getViewClass ( ) ) and
231
+ result .getADecorator ( ) = this .asExpr ( )
228
232
}
229
233
}
230
234
231
- /**
232
- * A view-class route-setup from the `view` decorator from a `aiohttp.web.RouteTableDef`.
233
- */
234
- class AiohttpViewRouteSetupFromDecorator extends AiohttpViewRouteSetup , DataFlow:: CallCfgNode {
235
- AiohttpViewRouteSetupFromDecorator ( ) {
236
- this =
237
- API:: moduleImport ( "aiohttp" )
238
- .getMember ( "web" )
239
- .getMember ( "RouteTableDef" )
240
- .getReturn ( )
241
- .getMember ( "view" )
242
- .getACall ( )
243
- }
244
-
245
- override DataFlow:: Node getUrlPatternArg ( ) {
246
- result in [ this .getArg ( 0 ) , this .getArgByName ( "path" ) ]
247
- }
248
-
249
- override DataFlow:: Node getViewClassArg ( ) { none ( ) }
250
-
251
- override Class getViewClass ( ) { result .getADecorator ( ) = this .asExpr ( ) }
252
- }
253
-
254
235
/** A class that we consider a aiohttp.web View class. */
255
236
abstract class AiohttpViewClass extends Class , SelfRefMixin {
256
237
/** Gets a function that could handle incoming requests, if any. */
@@ -269,7 +250,7 @@ module AiohttpWebModel {
269
250
270
251
/** A class that is used in a route-setup, therefore being considered a aiohttp.web View class. */
271
252
class AiohttpViewClassFromRouteSetup extends AiohttpViewClass {
272
- AiohttpViewClassFromRouteSetup ( ) { this = any ( AiohttpViewRouteSetup rs ) .getViewClass ( ) }
253
+ AiohttpViewClassFromRouteSetup ( ) { this = any ( AiohttpRouteSetup rs ) .getViewClass ( ) }
273
254
}
274
255
275
256
/** A request handler defined in an `aiohttp.web` view class, that has no known route. */
0 commit comments