def render(self, tri, notify=None): notify = notify or _dummy_fn notify('begin_print') notify('begin_map') map_pdf_path = gws.tempname('q.map.pdf') mro = self._render_map(tri, notify, map_pdf_path) notify('end_map') notify('begin_page') qgis_pdf_path = gws.tempname('q.qgis.pdf') self._render_qgis(tri, notify, mro, qgis_pdf_path) notify('end_page') if not mro: notify('end_print') return gws.ContentResponse(path=qgis_pdf_path) # merge qgis pdfs + map pdf # NB: qgis is ABOVE our map, so the qgis template and map must be transparent! # (this is because we need qgis to draw grids above the map) # @TODO automatic transparency notify('finalize_print') comb_path = gws.tempname('q.comb.pdf') gws.lib.pdf.overlay(map_pdf_path, qgis_pdf_path, comb_path) notify('end_print') return gws.ContentResponse(path=comb_path)
def sys_asset(self, req: gws.IWebRequest, p: SysAssetParams) -> gws.ContentResponse: locale_uid = p.localeUid or self.root.application.locale_uids[0] # eg. '8.0.0.light.css, 8.0.0.vendor.js etc if p.path.endswith('.vendor.js'): return gws.ContentResponse( content=gws.base.client.bundles.javascript( self.root, 'vendor', locale_uid), mime=gws.lib.mime.JS) if p.path.endswith('.util.js'): return gws.ContentResponse( content=gws.base.client.bundles.javascript( self.root, 'util', locale_uid), mime=gws.lib.mime.JS) if p.path.endswith('.app.js'): return gws.ContentResponse( content=gws.base.client.bundles.javascript( self.root, 'app', locale_uid), mime=gws.lib.mime.JS) if p.path.endswith('.css'): theme = p.path.split('.')[-2] return gws.ContentResponse(content=gws.base.client.bundles.css( self.root, 'app', theme), mime=gws.lib.mime.CSS)
def render(self, tri, notify=None): mp = tri.maps[0] mri = gws.MapRenderInput( background_color=mp.background_color, bbox=mp.bbox, center=mp.center, crs=tri.crs, dpi=tri.dpi, out_size=self.page_size, planes=mp.planes, rotation=mp.rotation, scale=mp.scale, ) notify = notify or (lambda a, b=None: None) notify('begin_print') notify('begin_page') notify('begin_map') mro = gws.gis.render.render_map(mri, notify) html = gws.gis.render.output_to_html_string(mro, wrap='fixed') notify('end_map') notify('end_page') notify('finalize_print') if not tri.out_mime or tri.out_mime == gws.lib.mime.HTML: notify('end_print') return gws.ContentResponse(mime=gws.lib.mime.HTML, content=html) if tri.out_mime == gws.lib.mime.PDF: res_path = gws.tempname('map.pdf') gws.lib.html2.render_to_pdf( html, out_path=res_path, page_size=self.page_size, ) notify('end_print') return gws.ContentResponse(path=res_path) if tri.out_mime == gws.lib.mime.PNG: res_path = gws.tempname('map.png') gws.lib.html2.render_to_png( html, out_path=res_path, page_size=self.page_size, ) notify('end_print') return gws.ContentResponse(path=res_path) raise gws.Error(f'invalid output mime: {tri.out_mime!r}')
def http_get_xy(self, req: gws.IWebRequest, p: GetFsParams) -> gws.ContentResponse: if not self.alkis: return gws.ContentResponse(mime='text/plain', content='error:') f = self._find_alkis_feature(p) if not f: gws.log.warn(f'gekos: not found {req.params!r}') return gws.ContentResponse(mime='text/plain', content='error:') return gws.ContentResponse(mime='text/plain', content='%.3f;%.3f' % (f.attr('x'), f.attr('y')))
def http_get_download(self, req: gws.IWebRequest, p: DownloadParams) -> gws.ContentResponse: with self.db.connect() as conn: docs = list( conn.select( f''' SELECT filename, data FROM {self.document_table.name} WHERE pn = %s AND deleted=0 ORDER BY title ''', [p.personUid])) buf = io.BytesIO() with zipfile.ZipFile(buf, 'w', compression=zipfile.ZIP_DEFLATED) as zf: for d in docs: zf.writestr(d['filename'], d['data']) return gws.ContentResponse( mime='application/zip', content=buf.getvalue(), )
def render_map_bbox_from_layer_caps_list(self, rd: Request, lcs: t.List[LayerCaps], bounds: gws.Bounds) -> gws.ContentResponse: try: px_width = int(rd.req.param('width')) px_height = int(rd.req.param('height')) except: raise gws.base.web.error.BadRequest() if not bounds or not px_width or not px_height: raise gws.base.web.error.BadRequest() mri = gws.MapRenderInput( background_color=0 if rd.req.param('transparent', '').lower() == 'false' else None, bbox=bounds.extent, crs=bounds.crs, out_size=(px_width, px_height, units.PX), planes=[ gws.MapRenderInputPlane(type='image_layer', layer=lc.layer) for lc in lcs ] ) mro = gws.gis.render.render_map(mri) if mro.planes and mro.planes[0].image: content = mro.planes[0].image.to_bytes() else: content = gws.lib.image.PIXEL_PNG8 return gws.ContentResponse(mime=gws.lib.mime.PNG, content=content)
def render(self, tri, notify=None): context = tri.context or {} context['gws'] = { 'version': gws.VERSION, 'endpoint': gws.SERVER_ENDPOINT, } def err(e, path, line): gws.log.warn( f'TEMPLATE: {e.__class__.__name__}:{e} in {path}:{line}') text = self.text if self.path: with open(self.path, 'rt') as fp: text = fp.read() content = chartreux.render( text, context, path=self.path or '<string>', error=err, ) mime = self.mimes[0] if self.mimes else 'text/plain' return gws.ContentResponse(content=content, mime=mime)
def http_get_features(self, req: gws.IWebRequest, p: GetFeaturesParams) -> gws.ContentResponse: # @TODO the response should be geojson FeatureCollection found = self._get_features(req, p) js = gws.lib.json2.to_string({ 'features': [gws.props(f, req.user, context=self) for f in found] }) return gws.ContentResponse(mime=gws.lib.mime.JSON, content=js)
def handle_getlegendgraphic(self, rd: core.Request): lcs = self.layer_caps_list_from_request(rd, ['layer', 'layers'], self.SCOPE_LEAF) if not lcs: raise gws.base.web.error.NotFound('No layers found') out = gws.gis.legend.render( gws.Legend(layers=[lc.layer for lc in lcs if lc.has_legend])) return gws.ContentResponse(mime='image/png', content=gws.gis.legend.to_bytes(out) or gws.lib.image.PIXEL_PNG8)
def handle_getlegendgraphic(self, rd: core.Request): # https://docs.geoserver.org/stable/en/user/services/wms/get_legend_graphic/index.html # @TODO currently only support 'layer' lcs = self.layer_caps_list_from_request(rd, ['layer', 'layers'], self.SCOPE_LAYER) if not lcs: raise gws.base.web.error.NotFound('No layers found') out = gws.gis.legend.render(gws.Legend(layers=[lc.layer for lc in lcs if lc.has_legend])) return gws.ContentResponse( mime=gws.lib.mime.PNG, content=gws.gis.legend.to_bytes(out) or gws.lib.image.PIXEL_PNG8)
def http_get_document(self, req: gws.IWebRequest, p: GetDocumentParams) -> gws.ContentResponse: cp = self.collection_proto_from_collection_uid(p.collectionUid) if not cp: raise gws.base.web.error.NotFound() doc = cp.get_document(p.collectionUid, p.documentUid) if not doc: raise gws.base.web.error.NotFound() return gws.ContentResponse(mime=doc.attr('mimetype'), content=doc.attr('data'), attachment_name=doc.attr('filename'))
def get_result(self, req: gws.IWebRequest, p: types.StatusParams) -> gws.ContentResponse: """Get the result of a print job as a byte stream""" job = gws.lib.job.get_for(self.root, req.user, p.jobUid) if not job or job.state != gws.lib.job.State.complete: raise gws.base.web.error.NotFound() res_path = core.job_result_path(job) if not res_path: raise gws.base.web.error.NotFound() return gws.ContentResponse(path=res_path)
def render(self, tri, notify=None): notify = notify or _dummy_fn notify('begin_print') if self.root.application.developer_option('template.always_reload'): if self.path: self.text = gws.read_file(self.path) parser = _Parser() rt = _Runtime(self, tri, notify) html = self._do_render(self.text, self.prepare_context(tri.context), parser, rt) notify('finalize_print') mime = tri.out_mime if not mime and self.mimes: mime = self.mimes[0] if not mime: mime = gws.lib.mime.HTML if mime == gws.lib.mime.HTML: notify('end_print') return gws.ContentResponse(mime=mime, content=html) if mime == gws.lib.mime.PDF: res_path = self._finalize_pdf(tri, html, parser) notify('end_print') return gws.ContentResponse(path=res_path) if mime == gws.lib.mime.PNG: res_path = self._finalize_png(tri, html, parser) notify('end_print') return gws.ContentResponse(path=res_path) raise gws.Error(f'invalid output mime: {tri.out_mime!r}')
def http_get_document(self, req: gws.IWebRequest, p: GetDocumentParams) -> gws.ContentResponse: with self.db.connect() as conn: doc = conn.select_one( f''' SELECT * FROM {self.document_table.name} WHERE {self.document_table.key_column} = %s AND deleted=0 ''', [p.documentUid]) if not doc: raise gws.base.web.error.NotFound() return gws.ContentResponse(mime=doc['mimetype'], content=doc['data'])
def _handle_request2(req: WebRequest) -> WebResponse: site = t.cast(gws.base.web.site.Object, req.site) cors = site.cors_options if cors and req.method == 'OPTIONS': return _with_cors_headers( cors, req.content_response( gws.ContentResponse(content='', mime='text/plain'))) req.auth_open() res = _handle_request3(req) req.auth_close(res) if cors and req.method == 'POST': res = _with_cors_headers(cors, res) return res
def handle_gettile(self, rd: core.Request): try: matrix_set_uid = rd.req.param('TILEMATRIXSET') matrix_uid = rd.req.param('TILEMATRIX') row = int(rd.req.param('TILEROW')) col = int(rd.req.param('TILECOL')) except Exception: raise gws.base.web.error.BadRequest() lcs = self.layer_caps_list_from_request(rd, ['layer'], self.SCOPE_LEAF) if not lcs: raise gws.base.web.error.NotFound() bounds = self._bounds_for_tile(matrix_set_uid, matrix_uid, row, col) if not bounds: raise gws.base.web.error.BadRequest() # crs = rd.project.map.crs # bbox = gws.gis.extent.transform(bbox, tm_crs, crs) mri = gws.MapRenderInput(background_color=None, bbox=bounds.extent, crs=bounds.crs, out_size=(256, 256, units.PX), planes=[ gws.MapRenderInputPlane( type='image_layer', layer=lc.layer) for lc in lcs ]) mro = gws.gis.render.render_map(mri) if mro.planes and mro.planes[0].image: content = mro.planes[0].image.to_bytes() else: content = gws.lib.image.PIXEL_PNG8 if self.root.application.developer_option('ows.annotate_wmts'): img = gws.lib.image.from_bytes(content) e = bounds.extent text = f"{matrix_uid} {row} {col}\n{e[0]}\n{e[1]}\n{e[2]}\n{e[3]}" content = img.add_text(text, x=10, y=10).add_box().to_bytes() return gws.ContentResponse(mime='image/png', content=content)
def _xml_error(self, err: Exception): try: status = int(gws.get(err, 'code', 500)) except Exception: status = 500 description = xml2.encode( gws.get(err, 'description') or f'Error {status}') xml = ( f'<?xml version="1.0" encoding="UTF-8"?>' + f'<ServiceExceptionReport>' + f'<ServiceException code="{status}">{description}</ServiceException>' + f'</ServiceExceptionReport>') # @TODO status, check OGC 17-007r1 return gws.ContentResponse(mime=gws.lib.mime.XML, content=xml, status=200)
def _handle_error(req: WebRequest, err: gws.base.web.error.HTTPException) -> WebResponse: # @TODO: image errors site = t.cast(gws.base.web.site.Object, req.site) if req.output_struct_type: return req.struct_response( gws.Response(error=gws.ResponseError( status=err.code, info=gws.get(err, 'description', '')))) if not site.error_page: return req.error_response(err) try: context = {'request': req, 'error': err.code} res = site.error_page.render(gws.TemplateRenderInput(context=context)) return req.content_response( gws.ContentResponse(content=res.content, mime=res.mime, status=err.code)) except: gws.log.exception() return req.error_response(gws.base.web.error.InternalServerError())
def handle_describerecord(self, rd: core.Request): xml = gws.read_file( gws.dirname(__file__) + '/templates/describeRecord.xml') return gws.ContentResponse(content=xml, mime=gws.lib.mime.XML)
def http_get_legend(self, req: gws.IWebRequest, p: GetLegendParams) -> gws.ContentResponse: r = self._get_legend(req, p) return gws.ContentResponse(mime=r.mime, content=r.content)
def _serve_path(root: gws.IRoot, req: gws.IWebRequest, p: GetAssetParams, as_attachment=False): spath = str(p.get('path') or '') if not spath: raise gws.base.web.error.NotFound() site_assets = req.site.assets_root project = None project_assets = None project_uid = p.get('projectUid') if project_uid: project = req.require_project(project_uid) project_assets = project.assets_root rpath = None if project_assets: rpath = _abs_path(spath, project_assets.dir) if not rpath and site_assets: rpath = _abs_path(spath, site_assets.dir) if not rpath: raise gws.base.web.error.NotFound() locale_uid = p.localeUid if project and locale_uid not in project.locale_uids: locale_uid = project.locale_uids[0] tpl = gws.base.template.create_from_path(root, rpath) if tpl: # give the template an empty response to manipulate (e.g. add 'location') res = gws.ContentResponse() context = { 'project': project, 'projects': _projects_for_user(root, req.user), 'request': req, 'user': req.user, 'params': p, 'response': res, 'localeUid': locale_uid, } render_res = tpl.render(gws.TemplateRenderInput(context=context)) if gws.is_empty(res): res = render_res return res mime = gws.lib.mime.for_path(rpath) if not _valid_mime_type(mime, project_assets, site_assets): gws.log.error(f'invalid mime path={rpath!r} mime={mime!r}') # NB: pretend the file doesn't exist raise gws.base.web.error.NotFound() gws.log.debug(f'serving {rpath!r} for {spath!r}') return gws.ContentResponse(mime=mime, path=rpath, as_attachment=as_attachment)
def to_xml(ARGS, tag): if ARGS.with_soap: tag = 'soap:Envelope', ('soap:Header', ''), ('soap:Body', tag) el = xml2.tag(*tag) xml = xml2.to_string(el, with_xml=True, with_xmlns=True, with_schemas=True) return gws.ContentResponse(content=xml, mime=gws.lib.mime.XML)