spring_web_dart 0.2.0
spring_web_dart: ^0.2.0 copied to clipboard
Spring Web for Dart: @GetMapping, @PathVariable, @RequestBody, ResponseEntity, server-sent events and HTTP/WebSocket client transports for the VM, Flutter and the web.
0.2.0 #
ResponseEntity.status(...).headers(h)replaces the values of those names like Spring'sputAll(it added them).ResponseEntityandResponseEntity.statustake only three-digit status codes (100–999), like Spring'sHttpStatusCode.valueOf; others throw anArgumentError.HttpResponseandStreamedHttpResponsetake those and 0, the opaque redirect a browser gives forfollowRedirects: false(any other code throws).HttpHeaders.addAll(name, values),addHeaders,putAll,setAll,clear,size,containsHeaderValue,isNotEmpty,==/hashCode(names in any case),HttpHeaders.readOnly(a view whose setters throw).ResponseEntity: read-only headers,==/hashCode,ResponseEntity.of/ofNullable(200 with the body, 404 without one).HttpResponse.bodyTextdecodes with thecharsetof theContent-Type, quoted or not and in any spelling Dart knows (onlycharset=iso-8859-1/latin1were seen);HttpResponse.decodeBody.HttpHeaders.lastModifiedis lenient like Spring's:nullfor a value that is not an HTTP date (it threw).MediaType.parseand the constructor check parameters like Spring: names are tokens, values tokens or quoted strings (also single quotes), no empty values, a legal charset name; a parameter without=is ignored (it threw) and a repeated name (any case) keeps the last value.MediaType.parse/parseMediaTypesgiveMediaTypeobjects withincludes,isCompatibleWith,charset,qualityValue,subtypeSuffix(Spring's rules for wildcards and+jsonsuffixes;InvalidMediaTypeException); more constants:applicationXml,applicationProblemJson,applicationProblemXml,applicationNdjson,applicationPdf,applicationYaml,textXml,textMarkdown, images, multipart, ...HttpHeaders.accept,eTag(quoted like Spring'ssetETag),ifNoneMatch,lastModified,date(HTTP dates: RFC 1123, RFC 850, asctime;formatDate/parseDate),contentDisposition(newContentDisposition,filename*for non-ASCII names),setContentDispositionFormData.ResponseEntity.status(...),created(uri),accepted(),noContent(),badRequest(),notFound(),unprocessableContent(),internalServerError()builders (header,headers,location,contentType,eTag,lastModified, thenbody(x)orbuild<T>()), andhasBody.- Breaking:
HttpMethod.parseis case-sensitive and does not trim, like Spring'sHttpMethod.valueOf('get'throws).
0.1.7 #
- Breaking:
HttpStatushas every Spring Framework 7 constant with Spring 7's names (unprocessableContentinstead ofunprocessableEntity,contentTooLarge, ...), as an extension type overint;reasonPhrase,series(HttpStatusSeries) andis1xxInformational/is2xxSuccessful/is3xxRedirection/is4xxClientError/is5xxServerError/isErrorare getters,valueOf/resolvefind a constant. The staticHttpStatus.reasonPhrase(int),isSuccess,isClientError,isServerErrorandisErrorare gone. - Breaking:
statusCodeofResponseEntity,HttpResponseandStreamedHttpResponseis anHttpStatusCode(still anint;HttpStatusCode.valueOffor any code). - Breaking:
HttpHeaders.forEachpasses each name once with all its values ((name, values), Spring 7); the name constants end inHeader(HttpHeaders.contentType→HttpHeaders.contentTypeHeader, alsoacceptHeader,authorizationHeader,contentLengthHeader,userAgentHeader) and there are many more. New:toSingleValueMap(),contentType,location,contentLength,setBearerAuth,setBasicAuth,encodeBasicAuth. - Breaking: mapping
headersuse Spring's'Name=value'syntax;'Name: value'is no longer accepted by clients. - Breaking:
WebSocketConnection→WebSocketSession(send→sendMessage,protocol→acceptedProtocol, newuriandisOpen;closeCode/closeReason→closeStatus);WebSocketStatus→CloseStatuswith Spring's constants (normal,goingAway,noStatusCode,noCloseFrame,serverError,serviceRestarted,serviceOverload, ...),close([CloseStatus status = CloseStatus.normal])(a normal closure by default, like Spring).MockWebSocket.url→uri,closeFromServer([CloseStatus]). HttpRequest.readTimeout: the longest wait for data (for the response, then between two chunks of the body), next totimeout(the whole exchange);HttpRequest.followRedirects(defaulttrue;IoHttpTransportno longer limits it toGETandHEADitself).- Breaking: mapping attributes next to a path use the
.ofconstructor, because the path is now an optional positional parameter:@GetMapping('/books', produces: ...)is@GetMapping.of(path: '/books', produces: ...)(alsoPostMapping,PutMapping,PatchMapping,DeleteMapping);@RequestMapping('/x', method: ...)is@RequestMapping.of(path: '/x', method: ...). pathis optional in@GetMapping()and the other mapping annotations ('': the base path of the client or class).requiredanddefaultValue(.ofconstructors) on@RequestParamand@RequestHeader,requiredon@PathVariable, as in Spring:requiredistrueby default, a default value impliesfalse, a nullable Dart parameter of a query parameter or header is never required.@CookieValue;@RequestBody(required:);@RequestParam/@RequestHeaderdocumentMapparameters (one query parameter / header per entry).- README: a "Differences from Spring" section.
0.1.6 #
- update road map
- ci: release with a button on main, skip new packages when publishing; shorter pubspec descriptions
0.1.5 #
- Initial version: Request mapping annotations, ResponseEntity, HttpHeaders, HTTP client transport (dart:io and fetch), MockHttpTransport.
- Streaming responses:
HttpTransport.streamandStreamedHttpResponse(dart:io and fetch). - Server-sent events:
EventStream<T>(aStream<T>with the whole events in.events),ServerSentEvent<T>,SseDecoder,connectServerSentEventswithEventSource-style reconnection (SseReconnect,Last-Event-ID),MediaType.textEventStream. - WebSocket transports:
WebSocketTransport,IoWebSocketTransport(dart:io),BrowserWebSocketTransport(js_interop),platformWebSocketTransport(),WebSocketStatus. - Testing:
MockHttpTransport.respondEvents/respondStream,MockWebSocketTransport. IoHttpTransport: request headers replaceHttpClient's defaults (aUser-Agentis no longer appended toDart/x (dart:io)).