Coverage for gws-app/gws/base/ows/server/error.py: 59%

70 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-16 22:59 +0200

1"""OWS-specific errors. 

2 

3Each error class corresponds to an OWS error code, as defined in OGC standards. 

4""" 

5 

6import gws 

7import gws.lib.xmlx as xmlx 

8import gws.lib.image 

9import gws.lib.mime 

10 

11 

12class Error(gws.Error): 

13 """OWS error.""" 

14 

15 def __init__(self, *args): 

16 super().__init__(*args) 

17 self.code = self.__class__.__name__ 

18 self.locator = self.args[0] if len(self.args) > 0 else '' 

19 self.message = self.args[1] if len(self.args) > 1 else '' 

20 # NB assume it's the user's fault by default 

21 self.status = _STATUS.get(self.code, 400) 

22 

23 def to_xml_response(self, xmlns='ows') -> gws.ContentResponse: 

24 """Returns an XML response for this error. 

25 

26 Args: 

27 xmlns: XML namespace to use (``ogc`` or ``ows``). 

28 """ 

29 

30 if xmlns == 'ows': 

31 # OWS ExceptionReport, as per OGC 06-121r9, 8.5 

32 ns = xmlx.namespace.require('ows11') 

33 xml = xmlx.tag( 

34 'ExceptionReport', 

35 ( 

36 'Exception', 

37 {'exceptionCode': self.code, 'locator': self.locator}, 

38 self.message, 

39 ), 

40 ) 

41 

42 elif xmlns == 'ogc': 

43 # OGC ServiceExceptionReport, as per OGC 06-042, H.2 

44 ns = xmlx.namespace.require('ogc') 

45 xml = xmlx.tag( 

46 'ServiceExceptionReport', 

47 ( 

48 'ServiceException', 

49 {'code': self.code}, 

50 self.message, 

51 ), 

52 ) 

53 

54 else: 

55 raise gws.Error(f'invalid {xmlns=}') 

56 

57 return gws.ContentResponse( 

58 status=self.status, 

59 mime=gws.lib.mime.XML, 

60 content=xml.to_string( 

61 gws.XmlOptions( 

62 defaultNamespace=ns, 

63 withXmlDeclaration=True, 

64 withNamespaceDeclarations=True, 

65 ) 

66 ), 

67 ) 

68 

69 def to_image_response(self, mime='image/png') -> gws.ContentResponse: 

70 """Returns an image response for this error. 

71 

72 Args: 

73 mime: Image mime type. 

74 """ 

75 

76 return gws.ContentResponse( 

77 status=self.status, 

78 mime=mime, 

79 content=gws.lib.image.error_pixel(mime), 

80 ) 

81 

82 

83def from_exception(exc: Exception) -> Error: 

84 """Convert an Exception to the OWS Error.""" 

85 

86 if isinstance(exc, Error): 

87 return exc 

88 

89 e = None 

90 

91 if isinstance(exc, gws.NotFoundError): 

92 e = NotFound() 

93 elif isinstance(exc, gws.ForbiddenError): 

94 e = Forbidden() 

95 elif isinstance(exc, gws.BadRequestError): 

96 e = BadRequest() 

97 

98 if e: 

99 gws.log.warning(f'OWS Exception: {e.code} cause={exc!r}') 

100 else: 

101 gws.log.exception() 

102 e = NoApplicableCode('', 'Internal Server Error') 

103 

104 e.__cause__ = exc 

105 return e 

106 

107 

108# @formatter:off 

109 

110# out extensions 

111 

112 

113class NotFound(Error): ... 

114 

115 

116class Forbidden(Error): ... 

117 

118 

119class BadRequest(Error): ... 

120 

121 

122# OGC 06-121r9 

123# Table 27 — Standard exception codes and meanings 

124 

125 

126class InvalidParameterValue(Error): ... 

127 

128 

129class InvalidUpdateSequence(Error): ... 

130 

131 

132class MissingParameterValue(Error): ... 

133 

134 

135class NoApplicableCode(Error): ... 

136 

137 

138class OperationNotSupported(Error): ... 

139 

140 

141class OptionNotSupported(Error): ... 

142 

143 

144class VersionNegotiationFailed(Error): ... 

145 

146 

147# OGC 06-042 

148# Table E.1 — Service exception codes 

149 

150 

151class CurrentUpdateSequence(Error): ... 

152 

153 

154class InvalidCRS(Error): ... 

155 

156 

157class InvalidDimensionValue(Error): ... 

158 

159 

160class InvalidFormat(Error): ... 

161 

162 

163class InvalidPoint(Error): ... 

164 

165 

166class LayerNotDefined(Error): ... 

167 

168 

169class LayerNotQueryable(Error): ... 

170 

171 

172class MissingDimensionValue(Error): ... 

173 

174 

175class StyleNotDefined(Error): ... 

176 

177 

178# OGC 07-057r7 

179# Table 20 — Exception codes for GetCapabilities operation 

180# Table 23 — Exception codes for GetTile operation 

181 

182 

183class PointIJOutOfRange(Error): ... 

184 

185 

186class TileOutOfRange(Error): ... 

187 

188 

189# OGC 09-025r1 

190# Table 3 — WFS exception codes 

191 

192 

193class CannotLockAllFeatures(Error): ... 

194 

195 

196class DuplicateStoredQueryIdValue(Error): ... 

197 

198 

199class DuplicateStoredQueryParameterName(Error): ... 

200 

201 

202class FeaturesNotLocked(Error): ... 

203 

204 

205class InvalidLockId(Error): ... 

206 

207 

208class InvalidValue(Error): ... 

209 

210 

211class LockHasExpired(Error): ... 

212 

213 

214class OperationParsingFailed(Error): ... 

215 

216 

217class OperationProcessingFailed(Error): ... 

218 

219 

220class ResponseCacheExpired(Error): ... 

221 

222 

223# OGC 06-121r9 8.6 HTTP STATUS codes for OGC Exceptions 

224 

225_STATUS = dict( 

226 OperationNotSupported=501, 

227 MissingParameterValue=400, 

228 InvalidParameterValue=400, 

229 VersionNegotiationFailed=400, 

230 InvalidUpdateSequence=400, 

231 OptionNotSupported=501, 

232 NoApplicableCode=500, 

233 NotFound=404, 

234 Forbidden=403, 

235 BadRequest=400, 

236)