├── .dockerignore
├── .gitattributes
├── .github
└── workflows
│ ├── build-push-gcr.yaml
│ ├── github-registry.yml
│ ├── iris-contest-workflows.yml
│ └── objectscript-quality.yml
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
└── settings.json
├── Dockerfile
├── LICENSE
├── README.md
├── dev.md
├── docker-compose.yml
├── iris.script
├── module.xml
└── src
└── dc
└── Sample
├── Person.cls
├── PersonREST.cls
└── REST
└── Base.cls
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.DS_Store
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.sh text eol=lf
2 | *.cls text eol=lf
3 | *.mac text eol=lf
4 | *.int text eol=lf
5 | *.xml text eol=lf
6 | Dockerfil* text eol=lf
--------------------------------------------------------------------------------
/.github/workflows/build-push-gcr.yaml:
--------------------------------------------------------------------------------
1 | name: Cloud Run Deploy
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - main
8 | workflow_dispatch:
9 |
10 | jobs:
11 | deploy:
12 | uses: intersystems-community/demo-deployment/.github/workflows/deployment.yml@master
13 | with:
14 | # Replace the name: parameter below to have your application deployed at
15 | # https://project-name.demo.community.intersystems.com/
16 | name: project-name
17 | secrets:
18 | # Do not forget to add Secret in GitHub Repoository Settings with name SERVICE_ACCOUNT_KEY
19 | SERVICE_ACCOUNT_KEY: ${{ secrets.SERVICE_ACCOUNT_KEY }}
--------------------------------------------------------------------------------
/.github/workflows/github-registry.yml:
--------------------------------------------------------------------------------
1 | name: Build and publish a Docker image to ghcr.io
2 | on:
3 |
4 | # publish on pushes to the main branch (image tagged as "latest")
5 | # image name: will be: ghcr.io/${{ github.repository }}:latest
6 | # e.g.: ghcr.io/intersystems-community/intersystems-iris-dev-template:latest
7 | push:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | docker_publish:
13 | runs-on: "ubuntu-20.04"
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 |
18 | # https://github.com/marketplace/actions/push-to-ghcr
19 | - name: Build and publish a Docker image for ${{ github.repository }}
20 | uses: macbre/push-to-ghcr@master
21 | with:
22 | image_name: ${{ github.repository }}
23 | github_token: ${{ secrets.GITHUB_TOKEN }}
24 | # optionally push to the Docker Hub (docker.io)
25 | # docker_io_token: ${{ secrets.DOCKER_IO_ACCESS_TOKEN }} # see https://hub.docker.com/settings/security
--------------------------------------------------------------------------------
/.github/workflows/iris-contest-workflows.yml:
--------------------------------------------------------------------------------
1 | name: objectscriptquality
2 | on: push
3 |
4 | jobs:
5 | linux:
6 | name: Linux build
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - name: Execute ObjectScript Quality Analysis
11 | run: wget https://raw.githubusercontent.com/litesolutions/objectscriptquality-jenkins-integration/master/iris-community-hook.sh && sh ./iris-community-hook.sh
12 |
--------------------------------------------------------------------------------
/.github/workflows/objectscript-quality.yml:
--------------------------------------------------------------------------------
1 | name: objectscriptquality
2 | on: push
3 |
4 | jobs:
5 | linux:
6 | name: Linux build
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - name: Execute ObjectScript Quality Analysis
11 | run: wget https://raw.githubusercontent.com/litesolutions/objectscriptquality-jenkins-integration/master/iris-community-hook.sh && sh ./iris-community-hook.sh
12 |
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | iris-main.log
3 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "eamodio.gitlens",
4 | "georgejames.gjlocate",
5 | "github.copilot",
6 | "intersystems-community.servermanager",
7 | "intersystems-community.sqltools-intersystems-driver",
8 | "intersystems-community.vscode-objectscript",
9 | "intersystems.language-server",
10 | "mohsen1.prettify-json",
11 | "ms-azuretools.vscode-docker",
12 | "ms-python.python",
13 | "ms-python.vscode-pylance",
14 | "ms-vscode-remote.remote-containers"
15 | ]
16 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "type": "objectscript",
6 | "request": "launch",
7 | "name": "ObjectScript Debug Class",
8 | "program": "##class(PackageSample.ObjectScript).Test()",
9 | },
10 | {
11 | "type": "objectscript",
12 | "request": "attach",
13 | "name": "ObjectScript Attach",
14 | "processId": "${command:PickProcess}",
15 | "system": true
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 |
4 | "iris.script": "objectscript"
5 | },
6 | "objectscript.conn" :{
7 | "ns": "USER",
8 | "username": "_SYSTEM",
9 | "password": "SYS",
10 | "docker-compose": {
11 | "service": "iris",
12 | "internalPort": 52773
13 | },
14 | "active": true,
15 | "links": {
16 | "Swagger": "${serverUrl}/swagger-ui/index.html"
17 | }
18 | }
19 |
20 |
21 | }
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG IMAGE=intersystemsdc/iris-community:2020.3.0.221.0-zpm
2 | ARG IMAGE=intersystemsdc/iris-community
3 | FROM $IMAGE
4 |
5 | WORKDIR /home/irisowner/dev
6 |
7 | RUN --mount=type=bind,src=.,dst=. \
8 | iris start IRIS && \
9 | iris session IRIS < iris.script && \
10 | iris stop IRIS quietly
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 InterSystems Developer Community
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## intersystems-iris-rest-api-template
2 |
3 | [](https://openexchange.intersystems.com/package/iris-rest-api-template)
4 | [](https://community.objectscriptquality.com/dashboard?id=intersystems_iris_community%2Firis-rest-api-template)
5 |
6 |
7 | This is a template of a REST API application built with ObjectScript in InterSystems IRIS.
8 | It also has OPEN API spec,
9 | can be developed with Docker and VSCode,
10 | can ve deployed as ZPM module.
11 |
12 | ## Prerequisites
13 | Make sure you have [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Docker desktop](https://www.docker.com/products/docker-desktop) installed.
14 |
15 | ## Installation with ZPM
16 |
17 | zpm:USER>install rest-api-template
18 |
19 | ## Installation for development
20 |
21 | Create your repository from template.
22 |
23 | Clone/git pull the repo into any local directory e.g. like it is shown below (here I show all the examples related to this repository, but I assume you have your own derived from the template):
24 |
25 | ```
26 | $ git clone git@github.com:intersystems-community/iris-rest-api-template.git
27 | ```
28 |
29 | Open the terminal in this directory and run:
30 |
31 | ```
32 | $ docker-compose up -d --build
33 | ```
34 |
35 | or open the folder in VSCode and do the following:
36 | 
37 |
38 |
39 | ## How to Work With it
40 |
41 | This template creates /crud REST web-application on IRIS which implements 4 types of communication: GET, POST, PUT and DELETE aka CRUD operations.
42 | These interface works with a sample persistent class dc.Sample.Person.
43 |
44 | Open http://localhost:52773/swagger-ui/index.html to test the REST API
45 |
46 | # Testing GET requests
47 |
48 | To test GET you need to have some data. You can create it with POST request (see below), or you can create some fake testing data. to do that open IRIS terminal or web terminal on /localhost:52773/terminal/ and call:
49 |
50 | ```
51 | USER>do ##class(dc.Sample.Person).AddTestData(10)
52 | ```
53 | This will create 10 random records in dc.Sample.Person class.
54 |
55 |
56 | You can get swagger Open API 2.0 documentation on:
57 | ```
58 | localhost:52773/crud/_spec
59 | ```
60 |
61 | This REST API exposes two GET requests: all the data and one record.
62 | To get all the data in JSON call:
63 |
64 | ```
65 | localhost:52773/crud/persons/all
66 | ```
67 |
68 | To request the data for a particular record provide the id in GET request like 'localhost:52773/crud/persons/id' . E.g.:
69 |
70 | ```
71 | localhost:52773/crud/persons/1
72 | ```
73 |
74 | This will return JSON data for the person with ID=1, something like that:
75 |
76 | ```
77 | {"Name":"Elon Mask","Title":"CEO","Company":"Tesla","Phone":"123-123-1233","DOB":"1982-01-19"}
78 | ```
79 |
80 | # Testing POST request
81 |
82 | Create a POST request e.g. in Postman with raw data in JSON. e.g.
83 |
84 | ```
85 | {"Name":"Elon Mask","Title":"CEO","Company":"Tesla","Phone":"123-123-1233","DOB":"1982-01-19"}
86 | ```
87 |
88 | Adjust the authorisation if needed - it is basic for container with default login and password for IRIR Community edition container
89 |
90 | and send the POST request to localhost:52773/crud/persons/
91 |
92 | This will create a record in dc.Sample.Person class of IRIS.
93 |
94 | # Testing PUT request
95 |
96 | PUT request could be used to update the records. This needs to send the similar JSON as in POST request above supplying the id of the updated record in URL.
97 | E.g. we want to change the record with id=5. Prepare in Postman the JSON in raw like following:
98 |
99 | ```
100 | {"Name":"Jeff Besos","Title":"CEO","Company":"Amazon","Phone":"123-123-1233","DOB":"1982-01-19"}
101 | ```
102 |
103 | and send the put request to:
104 | ```
105 | localhost:52773/crud/persons/5
106 | ```
107 |
108 | # Testing DELETE request
109 |
110 | For delete request this REST API expects only the id of the record to delete. E.g. if the id=5 the following DELETE call will delete the record:
111 |
112 | ```
113 | localhost:52773/crud/persons/5
114 | ```
115 |
116 | ## How to start coding
117 | This repository is ready to code in VSCode with ObjectScript plugin.
118 | Install [VSCode](https://code.visualstudio.com/) and [ObjectScript](https://marketplace.visualstudio.com/items?itemName=daimor.vscode-objectscript) plugin and open the folder in VSCode.
119 | Open /src/cls/PackageSample/ObjectScript.cls class and try to make changes - it will be compiled in running IRIS docker container.
120 |
121 | Feel free to delete PackageSample folder and place your ObjectScript classes in a form
122 | /src/cls/Package/Classname.cls
123 |
124 | The script in Installer.cls will import everything you place under /src/cls into IRIS.
125 |
126 | ## What's insde the repo
127 |
128 | # Dockerfile
129 |
130 | The simplest dockerfile to start IRIS and load ObjectScript from /src/cls folder
131 | Use the related docker-compose.yml to easily setup additional parametes like port number and where you map keys and host folders.
132 |
133 | # .vscode/settings.json
134 |
135 | Settings file to let you immedietly code in VSCode with [VSCode ObjectScript plugin](https://marketplace.visualstudio.com/items?itemName=daimor.vscode-objectscript))
136 |
137 | # .vscode/launch.json
138 | Config file if you want to debug with VSCode ObjectScript
139 |
--------------------------------------------------------------------------------
/dev.md:
--------------------------------------------------------------------------------
1 | # useful commands
2 | ## clean up docker
3 | use it when docker says "There is no space left on device". It will remove built but not used images and other temporary files.
4 | ```
5 | docker system prune -f
6 | ```
7 |
8 | ```
9 | docker rm -f $(docker ps -qa)
10 | ```
11 |
12 | ## build container with no cache
13 | ```
14 | docker-compose build --no-cache --progress=plain
15 | ```
16 | ## start iris container
17 | ```
18 | docker-compose up -d
19 | ```
20 |
21 | ## open iris terminal in docker
22 | ```
23 | docker exec iris iris session iris -U IRISAPP
24 | ```
25 |
26 |
27 | ## import objectscirpt code
28 |
29 | do $System.OBJ.LoadDir("/home/irisowner/dev/src","ck",,1)
30 | ## map iris key from Mac home directory to IRIS in container
31 | - ~/iris.key:/usr/irissys/mgr/iris.key
32 |
33 | ## install git in the docker image
34 | ## add git in dockerfile
35 | USER root
36 | RUN apt update && apt-get -y install git
37 |
38 | USER ${ISC_PACKAGE_MGRUSER}
39 |
40 |
41 | ## install docker-compose
42 | ```
43 | sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
44 |
45 | sudo chmod +x /usr/local/bin/docker-compose
46 |
47 | ```
48 |
49 | ## load and test module
50 | ```
51 |
52 | zpm "load /home/irisowner/dev"
53 |
54 | zpm "test dc-sample"
55 | ```
56 |
57 | ## select zpm test registry
58 | ```
59 | repo -n registry -r -url https://test.pm.community.intersystems.com/registry/ -user test -pass PassWord42
60 | ```
61 |
62 | ## get back to public zpm registry
63 | ```
64 | repo -r -n registry -url https://pm.community.intersystems.com/ -user "" -pass ""
65 | ```
66 |
67 | ## export a global in runtime into the repo
68 | ```
69 | d $System.OBJ.Export("GlobalD.GBL","/irisrun/repo/src/gbl/GlobalD.xml")
70 | ```
71 |
72 | ## create a web app in dockerfile
73 | ```
74 | zn "%SYS" \
75 | write "Create web application ...",! \
76 | set webName = "/csp/irisweb" \
77 | set webProperties("NameSpace") = "IRISAPP" \
78 | set webProperties("Enabled") = 1 \
79 | set webProperties("CSPZENEnabled") = 1 \
80 | set webProperties("AutheEnabled") = 32 \
81 | set webProperties("iKnowEnabled") = 1 \
82 | set webProperties("DeepSeeEnabled") = 1 \
83 | set sc = ##class(Security.Applications).Create(webName, .webProperties) \
84 | write "Web application "_webName_" has been created!",!
85 | ```
86 |
87 |
88 |
89 | ```
90 | do $SYSTEM.OBJ.ImportDir("/opt/irisbuild/src",, "ck")
91 | ```
92 |
93 |
94 | ### run tests described in the module
95 |
96 | IRISAPP>zpm
97 | IRISAPP:zpm>load /irisrun/repo
98 | IRISAPP:zpm>test package-name
99 |
100 | ### install ZPM with one line
101 | // Install ZPM
102 | set $namespace="%SYS", name="DefaultSSL" do:'##class(Security.SSLConfigs).Exists(name) ##class(Security.SSLConfigs).Create(name) set url="https://pm.community.intersystems.com/packages/zpm/latest/installer" Do ##class(%Net.URLParser).Parse(url,.comp) set ht = ##class(%Net.HttpRequest).%New(), ht.Server = comp("host"), ht.Port = 443, ht.Https=1, ht.SSLConfiguration=name, st=ht.Get(comp("path")) quit:'st $System.Status.GetErrorText(st) set xml=##class(%File).TempFilename("xml"), tFile = ##class(%Stream.FileBinary).%New(), tFile.Filename = xml do tFile.CopyFromAndSave(ht.HttpResponse.Data) do ht.%Close(), $system.OBJ.Load(xml,"ck") do ##class(%File).Delete(xml)
103 |
104 |
105 |
106 |
107 | docker run --rm --name iris-sql -d -p 9091:1972 -p 9092:52773 -e IRIS_PASSWORD=demo -e IRIS_USERNAME=demo intersystemsdc/iris-community
108 |
109 |
110 | docker run --rm --name iris-ce -d -p 9091:1972 -p 9092:52773 -e IRIS_PASSWORD=demo -e IRIS_USERNAME=demo intersystemsdc/iris-community -a "echo 'zpm \"install webterminal\"' | iriscli"
111 |
112 |
113 |
114 | docker run --rm --name iris-sql -d -p 9092:52773 containers.intersystems.com/intersystems/iris-community:2023.1.0.229.0
115 |
116 |
117 | docker run --rm --name iris-ce -d -p 9092:52773 containers.intersystems.com/intersystems/iris-community:2023.1.0.229.0
118 |
119 |
120 | list all the specs:
121 | http://localhost:52773/api/mgmnt/
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.6'
2 | services:
3 | iris:
4 | build:
5 | context: .
6 | dockerfile: Dockerfile
7 | restart: always
8 | ports:
9 | - 51773:1972
10 | - 52773:52773
11 | - 53773
12 | volumes:
13 | - ./:/home/irisowner/dev
14 |
--------------------------------------------------------------------------------
/iris.script:
--------------------------------------------------------------------------------
1 | ;do $System.OBJ.LoadDir("/opt/irisapp/src","ck",,1)
2 |
3 | zn "%SYS"
4 | Do ##class(Security.Users).UnExpireUserPasswords("*")
5 | zpm "install passwordless"
6 |
7 | zn "USER"
8 | zpm "load /home/irisowner/dev/ -v":1
9 |
10 |
11 | halt
12 |
--------------------------------------------------------------------------------
/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | rest-api-template
6 | 1.1.0
7 | module
8 | src
9 |
10 |
11 |
12 | swagger-ui
13 | 1.*.*
14 |
15 |
16 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/dc/Sample/Person.cls:
--------------------------------------------------------------------------------
1 | Class dc.Sample.Person Extends (%Persistent, %JSON.Adaptor, %Populate)
2 | {
3 |
4 | Property Name As %VarString;
5 |
6 | Property Title As %String;
7 |
8 | Property Company As %String;
9 |
10 | Property Phone As %VarString;
11 |
12 | Property DOB As %Date(MAXVAL = "$piece($horolog, "","", 1)");
13 |
14 | /// Index for property DOB
15 | Index DOBIndex On DOB;
16 |
17 | ClassMethod AddTestData(amount As %Integer = 10)
18 | {
19 | d ..Populate(amount)
20 | }
21 |
22 | Storage Default
23 | {
24 |
25 |
26 | %%CLASSNAME
27 |
28 |
29 | Name
30 |
31 |
32 | Title
33 |
34 |
35 | Company
36 |
37 |
38 | Phone
39 |
40 |
41 | DOB
42 |
43 |
44 | ^Sample.PersonD
45 | PersonDefaultData
46 | ^Sample.PersonD
47 | ^Sample.PersonI
48 | ^Sample.PersonS
49 | %Storage.Persistent
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/dc/Sample/PersonREST.cls:
--------------------------------------------------------------------------------
1 | Class dc.Sample.PersonREST Extends Sample.REST.Base
2 | {
3 |
4 | Parameter Version = "1.0.6";
5 |
6 | XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
7 | {
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | }
29 |
30 | /// PersonsREST general information
31 | ClassMethod GetInfo() As %Status
32 | {
33 | SET version = ..#Version
34 | SET info = {
35 | "version": (version)
36 | }
37 | RETURN ..%ProcessResult($$$OK, info)
38 | }
39 |
40 | /// Retreive all the records of dc.Sample.Person
41 | ClassMethod GetAllPersons() As %Status
42 | {
43 |
44 | #dim tSC As %Status = $$$OK
45 |
46 | Set rset = ##class(dc.Sample.Person).ExtentFunc()
47 |
48 | Set %response.ContentType = ..#CONTENTTYPEJSON
49 | Write "["
50 | if rset.%Next() {
51 | Set person = ##class(dc.Sample.Person).%OpenId(rset.ID)
52 | Do person.%JSONExport()
53 | }
54 | While rset.%Next() {
55 | Write ","
56 | Set person = ##class(dc.Sample.Person).%OpenId(rset.ID)
57 | Do person.%JSONExport()
58 | }
59 | Write "]"
60 | Quit tSC
61 | }
62 |
63 | /// Return one record fo dc.Sample.Person
64 | ClassMethod GetPerson(id As %Integer) As %Status
65 | {
66 | #dim tSC As %Status = $$$OK
67 | #dim e As %Exception.AbstractException
68 |
69 |
70 | #; Set the response header to plain text
71 | Set %response.ContentType = ..#CONTENTTYPEJSON
72 |
73 | Set person = ##class(dc.Sample.Person).%OpenId(id)
74 |
75 | If '$IsObject(person) Quit ..Http404()
76 |
77 | Do person.%JSONExport()
78 |
79 | Quit tSC
80 | }
81 |
82 | /// Creates a new dc.Sample.Person record
83 | ClassMethod CreatePerson() As %Status
84 | {
85 | #dim tSC As %Status = $$$OK
86 | #dim e As %Exception.AbstractException
87 | Set person = ##class(dc.Sample.Person).%New()
88 | Set data=%request.Content
89 |
90 |
91 | $$$TOE(tSC,person.%JSONImport(data))
92 | $$$TOE(tSC,person.%Save())
93 |
94 | Set %response.Status = 204
95 | Set %response.ContentType = ..#CONTENTTYPEJSON
96 | //d data.%ToJSON()
97 | Do person.%JSONExport()
98 |
99 | Quit tSC
100 | }
101 |
102 | /// Update a record in dc.Sample.Person with id
103 | ClassMethod UpdatePerson(id As %Integer) As %Status
104 | {
105 | #dim tSC As %Status = $$$OK
106 | #dim e As %Exception.AbstractException
107 | Set person = ##class(dc.Sample.Person).%OpenId(id)
108 | If '$IsObject(person) Return ..Http404()
109 | Set data=%request.Content
110 |
111 | $$$TOE(tSC,person.%JSONImport(data))
112 | $$$TOE(tSC,person.%Save())
113 |
114 | Set %response.Status = 200
115 |
116 | Set %response.ContentType = ..#CONTENTTYPEJSON
117 | Do person.%JSONExport()
118 |
119 | Quit tSC
120 | }
121 |
122 | /// Delete a record with id in dc.Sample.Person
123 | ClassMethod DeletePerson(id As %Integer) As %Status
124 | {
125 | #dim tSC As %Status = $$$OK
126 | #dim e As %Exception.AbstractException
127 | Set person = ##class(dc.Sample.Person).%OpenId(id)
128 | If '$IsObject(person) Return ..Http404()
129 |
130 | $$$TOE(tSC,person.%DeleteId(id))
131 |
132 | Set %response.Status = 200
133 |
134 | Set %response.ContentType = ..#CONTENTTYPEJSON
135 |
136 | Quit tSC
137 | }
138 |
139 | ClassMethod CreateRandomPersons(amount As %Integer) as %Status
140 | {
141 | #dim tSC As %Status = $$$OK
142 | Set %response.ContentType = ..#CONTENTTYPEJSON
143 |
144 | Try {
145 | set status = ##class(dc.Sample.Person).AddTestData(amount)
146 | $$$ThrowOnError(status)
147 | Set message = "Created "_amount_" random persons in Sample.Person data"
148 | } Catch(ex) {
149 | Set tSC = ex.Code
150 | }
151 | Return tSC
152 | }
153 |
154 | ClassMethod SwaggerSpec() As %Status
155 | {
156 | Set tSC = ##class(%REST.API).GetWebRESTApplication($NAMESPACE, %request.Application, .swagger)
157 | Do swagger.info.%Remove("x-ISC_Namespace")
158 | Set swagger.basePath = "/crud"
159 | Set swagger.info.title = "InterSystems IRIS REST CRUD demo"
160 | Set swagger.info.version = "0.1"
161 | Set swagger.host = "localhost:52773"
162 | Return ..%ProcessResult($$$OK, swagger)
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/src/dc/Sample/REST/Base.cls:
--------------------------------------------------------------------------------
1 | Class Sample.REST.Base Extends %CSP.REST [ System = 3 ]
2 | {
3 |
4 | Parameter CHARSET = "utf-8";
5 |
6 | Parameter CONTENTTYPE = "application/json";
7 |
8 | Parameter HandleCorsRequest = 1;
9 |
10 | Parameter PAGESIZE As INTEGER = 20;
11 |
12 | ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue As %Boolean) As %Status
13 | {
14 | SET tSC = $$$OK
15 | TRY {
16 |
17 | // Set the return type according to the Accept type in the request. Default is application/json.
18 | IF ('..AcceptsContentType(..#CONTENTTYPEJSON)) {
19 | SET tSC = ..ReportHttpStatusCode(..#HTTP406NOTACCEPTABLE), pContinue=0
20 | QUIT
21 | } ELSE {
22 | // This always returns json
23 | SET %response.ContentType=..#CONTENTTYPEJSON
24 | }
25 |
26 |
27 | // read request object into %DynamicObject format
28 | IF ((pMethod'="POST") && (pMethod'="PUT")) || (%request.Content="") {
29 | SET %request.Content = {}
30 | } ELSE {
31 | IF '$isobject(%request.Content) {
32 | SET tContent = %request.Content
33 | } ELSE {
34 | SET tContent = ""
35 | WHILE '%request.Content.AtEnd {
36 | SET tContent = tContent_%request.Content.Read()
37 | }
38 | }
39 | IF (tContent="") {
40 | SET %request.Content = {}
41 | } ELSE {
42 | SET tContent = $zconvert(tContent, "I", "UTF8")
43 | SET %request.Content = ##class(%Library.DynamicObject).%FromJSON(tContent)
44 | }
45 | }
46 |
47 | } CATCH ex {
48 | SET tSC = ex.AsStatus()
49 | }
50 | QUIT ##class(%iKnow.REST.Base).%ErrorHandler(tSC, .pContinue)
51 | }
52 |
53 | ClassMethod %ProcessResult(pStatus As %Status = {$$$OK}, pResult As %DynamicObject = "") As %Status [ Internal ]
54 | {
55 | #dim %response As %CSP.Response
56 | SET tSC = $$$OK
57 | IF $$$ISERR(pStatus) {
58 | SET %response.Status = 500
59 | SET tSC = ..StatusToJSON(pStatus, .tJSON)
60 | IF $isobject(tJSON) {
61 | SET pResult = tJSON
62 | } ELSE {
63 | SET pResult = { "errors": [ { "error": "Unknown error parsing status code" } ] }
64 | }
65 | }
66 | ELSEIF pStatus=1 {
67 | IF '$isobject(pResult){
68 | SET pResult = {
69 | }
70 | }
71 | }
72 | ELSE {
73 | SET %response.Status = pStatus
74 | SET error = $PIECE(pStatus, " ", 2, *)
75 | SET pResult = {
76 | "error": (error)
77 | }
78 | }
79 |
80 | IF pResult.%Extends("%Library.DynamicAbstractObject") {
81 | WRITE pResult.%ToJSON()
82 | }
83 | ELSEIF pResult.%Extends("%JSON.Adaptor") {
84 | DO pResult.%JSONExport()
85 | }
86 | ELSEIF pResult.%Extends("%Stream.Object") {
87 | DO pResult.OutputToDevice()
88 | }
89 |
90 | QUIT tSC
91 | }
92 |
93 | ClassMethod ReportHttpStatusCode(pHttpStatus, pSC As %Status = {$$$OK}) As %Status
94 | {
95 | Set %response.Status=pHttpStatus
96 |
97 | If $$$ISERR(pSC) Do ..outputStatus(pSC)
98 | /*
99 | If (+pHttpStatus>=400) {
100 | Set %response.ContentType = "application/json"
101 | SET pResult = {
102 | "error": ($PIECE(pHttpStatus, " ", 2, *))
103 | }
104 | Return ..%ProcessResult($$$OK, pResult)
105 | }*/
106 |
107 | Return $$$OK
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------