mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	docs: Wrap a bunch of long lines.
This commit is contained in:
		@@ -192,8 +192,10 @@ mind:
 | 
				
			|||||||
  Browsing this list can be a great way to find feature ideas to
 | 
					  Browsing this list can be a great way to find feature ideas to
 | 
				
			||||||
  implement that other Zulip users are excited about.
 | 
					  implement that other Zulip users are excited about.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* [2016 roadmap milestone](http://zulip.readthedocs.io/en/latest/roadmap.html): The
 | 
					* [2016 roadmap milestone](http://zulip.readthedocs.io/en/latest/roadmap.html):
 | 
				
			||||||
  projects that are [priorities for the Zulip project](https://zulip.readthedocs.io/en/latest/roadmap.html).  These are great projects if you're looking to make an impact.
 | 
					  The projects that are
 | 
				
			||||||
 | 
					  [priorities for the Zulip project](https://zulip.readthedocs.io/en/latest/roadmap.html).
 | 
				
			||||||
 | 
					  These are great projects if you're looking to make an impact.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Another way to find issues in Zulip is to take advantage of our
 | 
					Another way to find issues in Zulip is to take advantage of our
 | 
				
			||||||
"area:<foo>" convention in separating out issues.  We partition all of
 | 
					"area:<foo>" convention in separating out issues.  We partition all of
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,41 +42,59 @@ It presumes that you already have a fully implemented `<my-bot>.py` bot and now
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
3. Register a new bot on your Zulip server's web interface.
 | 
					3. Register a new bot on your Zulip server's web interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * Navigate to *Settings* -> *Your Bots* -> *Add a New Bot*, fill out the form and click on *Create Bot*.
 | 
					    * Navigate to *Settings* -> *Your Bots* -> *Add a New Bot*, fill
 | 
				
			||||||
 | 
					      out the form and click on *Create Bot*.
 | 
				
			||||||
    * A new bot should appear in the *Your Bots* panel.
 | 
					    * A new bot should appear in the *Your Bots* panel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
4. Add the bot's configuration file on your Zulip server.
 | 
					4. Add the bot's configuration file on your Zulip server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * In the *Your Bots* panel, click on the green icon to download its configuration file *.zuliprc* (the structure of this file is explained [here](#configuration-file).
 | 
					    * In the *Your Bots* panel, click on the green icon to download
 | 
				
			||||||
 | 
					      its configuration file *.zuliprc* (the structure of this file is
 | 
				
			||||||
 | 
					      explained [here](#configuration-file).
 | 
				
			||||||
    * Copy the file to a destination of your choice on your Zulip server, e.g. to `~/.zuliprc` or `~/zuliprc-test`.
 | 
					    * Copy the file to a destination of your choice on your Zulip server, e.g. to `~/.zuliprc` or `~/zuliprc-test`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
5. Subscribe the bot to the streams that the bot needs to read messages from or write messages to.
 | 
					5. Subscribe the bot to the streams that the bot needs to read messages from or write messages to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * To subscribe your bot to streams, navigate to *Manage Streams*. Select a stream and add your bot by its email address (the address you assigned in step 3).
 | 
					    * To subscribe your bot to streams, navigate to *Manage
 | 
				
			||||||
 | 
					      Streams*. Select a stream and add your bot by its email address
 | 
				
			||||||
 | 
					      (the address you assigned in step 3).
 | 
				
			||||||
    * Now, the bot will do its job on the streams you subscribed it to.
 | 
					    * Now, the bot will do its job on the streams you subscribed it to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
6. Run the bot.
 | 
					6. Run the bot.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * On your Zulip server (and outside the Vagrant environment), navigate to `~/zulip/contrib_bots/`
 | 
					    * On your Zulip server (and outside the Vagrant environment), navigate to `~/zulip/contrib_bots/`
 | 
				
			||||||
    * Run `python run.py ~/zulip/contrib_bots/lib/<my-bot>.py --config-file ~/.zuliprc`. The `~/` before `.zuliprc` should point to the directory containing the file (in this case, it is the home directory).
 | 
					    * Run `python run.py ~/zulip/contrib_bots/lib/<my-bot>.py
 | 
				
			||||||
    * Check the output of the command. It should start with the text the `usage` function returns, followed by logging output similar to this:
 | 
					      --config-file ~/.zuliprc`. The `~/` before `.zuliprc` should
 | 
				
			||||||
    ```
 | 
					      point to the directory containing the file (in this case, it is
 | 
				
			||||||
    INFO:root:starting message handling...
 | 
					      the home directory).
 | 
				
			||||||
    INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost
 | 
					    * Check the output of the command. It should start with the text
 | 
				
			||||||
    ```
 | 
					      the `usage` function returns, followed by logging output similar
 | 
				
			||||||
 | 
					      to this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      ```
 | 
				
			||||||
 | 
					      INFO:root:starting message handling...
 | 
				
			||||||
 | 
					      INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost
 | 
				
			||||||
 | 
					      ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    * Congrats! Now, your bot should be ready to test on the streams you've subscribed it to.
 | 
					    * Congrats! Now, your bot should be ready to test on the streams you've subscribed it to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Test the `followup.py` bot
 | 
					### Test the `followup.py` bot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Do the previous steps for the `followup.py` bot.
 | 
					1. Do the previous steps for the `followup.py` bot.
 | 
				
			||||||
2. Create the *followup* stream.
 | 
					2. Create the *followup* stream.
 | 
				
			||||||
3. Subscribe the bot to the newly created *followup* stream and a stream you want to use it from, e.g. *social*.
 | 
					3. Subscribe the bot to the newly created *followup* stream and a
 | 
				
			||||||
4. Send a message to the stream you've subscribed the bot to (other than *followup*). If everything works, a copy of the message should now pop up in the *followup* stream.
 | 
					   stream you want to use it from, e.g. *social*.
 | 
				
			||||||
 | 
					4. Send a message to the stream you've subscribed the bot to (other
 | 
				
			||||||
 | 
					   than *followup*). If everything works, a copy of the message should
 | 
				
			||||||
 | 
					   now pop up in the *followup* stream.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## How to develop a bot
 | 
					## How to develop a bot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The tutorial below explains the structure of a bot `<my-bot>.py`. You can use this as boilerplate code for developing your own bot.
 | 
					The tutorial below explains the structure of a bot `<my-bot>.py`. You
 | 
				
			||||||
 | 
					can use this as boilerplate code for developing your own bot.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Every bot is built upon this structure:
 | 
					Every bot is built upon this structure:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
class MyBotHandler(object):
 | 
					class MyBotHandler(object):
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
@@ -94,7 +112,11 @@ class MyBotHandler(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
handler_class = MyBotHandler
 | 
					handler_class = MyBotHandler
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
* The class name (in this case *MyBotHandler*) can be defined by you and should match the name of your bot. To register your bot's class, adjust the last line `handler_class = MyBotHandler` to match your class name.
 | 
					
 | 
				
			||||||
 | 
					* The class name (in this case *MyBotHandler*) can be defined by you
 | 
				
			||||||
 | 
					  and should match the name of your bot. To register your bot's class,
 | 
				
			||||||
 | 
					  adjust the last line `handler_class = MyBotHandler` to match your
 | 
				
			||||||
 | 
					  class name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Every bot needs to implement the functions
 | 
					* Every bot needs to implement the functions
 | 
				
			||||||
    * `usage(self)`
 | 
					    * `usage(self)`
 | 
				
			||||||
@@ -104,7 +126,9 @@ handler_class = MyBotHandler
 | 
				
			|||||||
* These functions are documented in the [next section](#bot-api).
 | 
					* These functions are documented in the [next section](#bot-api).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Bot API
 | 
					## Bot API
 | 
				
			||||||
This section documents the functions every bot needs to implement and the structure of the bot's config file.
 | 
					
 | 
				
			||||||
 | 
					This section documents the functions every bot needs to implement and
 | 
				
			||||||
 | 
					the structure of the bot's config file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### usage
 | 
					### usage
 | 
				
			||||||
*usage(self)*
 | 
					*usage(self)*
 | 
				
			||||||
@@ -212,13 +236,17 @@ None.
 | 
				
			|||||||
 site=<dev-url>
 | 
					 site=<dev-url>
 | 
				
			||||||
 ```
 | 
					 ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* key - the API key you created for the bot; this is how Zulip knows the request is from an authorized user.
 | 
					* key - the API key you created for the bot; this is how Zulip knows
 | 
				
			||||||
 | 
					  the request is from an authorized user.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* email - the email address of the bot, e.g. `some-bot@zulip.com`
 | 
					* email - the email address of the bot, e.g. `some-bot@zulip.com`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* site - your development environment URL; if you are working on a development environment hosted on your computer, use `localhost:9991`
 | 
					* site - your development environment URL; if you are working on a
 | 
				
			||||||
 | 
					  development environment hosted on your computer, use
 | 
				
			||||||
 | 
					  `localhost:9991`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Common problems
 | 
					## Common problems
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* I modified my bot's code, yet the changes don't seem to have an effect.
 | 
					* I modified my bot's code, yet the changes don't seem to have an effect.
 | 
				
			||||||
    * Ensure that you restarted the `run.py` script.
 | 
					    * Ensure that you restarted the `run.py` script.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -320,7 +320,11 @@ Now run these commands:
 | 
				
			|||||||
./tools/install-mypy
 | 
					./tools/install-mypy
 | 
				
			||||||
./tools/setup/emoji/build_emoji
 | 
					./tools/setup/emoji/build_emoji
 | 
				
			||||||
./scripts/setup/generate_secrets.py --development
 | 
					./scripts/setup/generate_secrets.py --development
 | 
				
			||||||
if [ $(uname) = "OpenBSD" ]; then sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /var/postgresql/tsearch_data/; else sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /usr/share/postgresql/9.*/tsearch_data/; fi
 | 
					if [ $(uname) = "OpenBSD" ]; then
 | 
				
			||||||
 | 
					    sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /var/postgresql/tsearch_data/
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /usr/share/postgresql/9.*/tsearch_data/
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
./scripts/setup/configure-rabbitmq
 | 
					./scripts/setup/configure-rabbitmq
 | 
				
			||||||
./tools/setup/postgres-init-dev-db
 | 
					./tools/setup/postgres-init-dev-db
 | 
				
			||||||
./tools/do-destroy-rebuild-database
 | 
					./tools/do-destroy-rebuild-database
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,9 +13,13 @@ Zulip uses the [Django web
 | 
				
			|||||||
framework](https://docs.djangoproject.com/en/1.8/), so a lot of these
 | 
					framework](https://docs.djangoproject.com/en/1.8/), so a lot of these
 | 
				
			||||||
paths will be familiar to Django developers.
 | 
					paths will be familiar to Django developers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `zproject/urls.py` Main [Django routes file](https://docs.djangoproject.com/en/1.8/topics/http/urls/).  Defines which URLs are handled by which view functions or templates.
 | 
					* `zproject/urls.py` Main
 | 
				
			||||||
 | 
					  [Django routes file](https://docs.djangoproject.com/en/1.8/topics/http/urls/).
 | 
				
			||||||
 | 
					  Defines which URLs are handled by which view functions or templates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `zerver/models.py` Main [Django models](https://docs.djangoproject.com/en/1.8/topics/db/models/) file.  Defines Zulip's database tables.
 | 
					* `zerver/models.py` Main
 | 
				
			||||||
 | 
					  [Django models](https://docs.djangoproject.com/en/1.8/topics/db/models/)
 | 
				
			||||||
 | 
					  file.  Defines Zulip's database tables.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `zerver/lib/actions.py` Most code doing writes to user-facing database tables.
 | 
					* `zerver/lib/actions.py` Most code doing writes to user-facing database tables.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,7 +44,8 @@ paths will be familiar to Django developers.
 | 
				
			|||||||
See [our translating docs](translating.html) for details on Zulip's
 | 
					See [our translating docs](translating.html) for details on Zulip's
 | 
				
			||||||
templating systems.
 | 
					templating systems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `templates/zerver/` For [Jinja2](http://jinja.pocoo.org/) templates for the backend (for zerver app).
 | 
					* `templates/zerver/` For [Jinja2](http://jinja.pocoo.org/) templates
 | 
				
			||||||
 | 
					  for the backend (for zerver app).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `static/templates/` [Handlebars](http://handlebarsjs.com/) templates for the frontend.
 | 
					* `static/templates/` [Handlebars](http://handlebarsjs.com/) templates for the frontend.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,10 +21,14 @@ are in your git checkout under `static`, and are served unminified.
 | 
				
			|||||||
## Nginx secures traffic with [SSL](prod-install.html)
 | 
					## Nginx secures traffic with [SSL](prod-install.html)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you visit your Zulip server in your browser and discover that your
 | 
					If you visit your Zulip server in your browser and discover that your
 | 
				
			||||||
traffic isn't being properly encrypted, an [nginx misconfiguration](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/sites-available/zulip-enterprise) is the
 | 
					traffic isn't being properly encrypted, an [nginx misconfiguration][nginx-config] is the
 | 
				
			||||||
likely culprit.
 | 
					likely culprit.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Static files are [served directly](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app) by Nginx
 | 
					[nginx-config]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/sites-available/zulip-enterprise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Static files are [served directly][served-directly] by Nginx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[served-directly]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Static files include JavaScript, css, static assets (like emoji, avatars),
 | 
					Static files include JavaScript, css, static assets (like emoji, avatars),
 | 
				
			||||||
and user uploads (if stored locally and not on S3).
 | 
					and user uploads (if stored locally and not on S3).
 | 
				
			||||||
@@ -36,7 +40,9 @@ location /static/ {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Nginx routes other requests [between tornado and django](architecture-overview.html?highlight=tornado#tornado-and-django)
 | 
					## Nginx routes other requests [between tornado and django][tornado-django]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[tornado-django]: architecture-overview.html?highlight=tornado#tornado-and-django
 | 
				
			||||||
 | 
					
 | 
				
			||||||
All our connected clients hold open long-polling connections so that
 | 
					All our connected clients hold open long-polling connections so that
 | 
				
			||||||
they can recieve events (messages, presence notifications, and so on) in
 | 
					they can recieve events (messages, presence notifications, and so on) in
 | 
				
			||||||
@@ -45,7 +51,9 @@ real-time. Events are served by Zulip's `tornado` application.
 | 
				
			|||||||
Nearly every other kind of request is served by the `zerver` Django
 | 
					Nearly every other kind of request is served by the `zerver` Django
 | 
				
			||||||
application.
 | 
					application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[Here is the relevant nginx routing configuration.](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app)
 | 
					[Here is the relevant nginx routing configuration.][nginx-config-link]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[nginx-config-link]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Django routes the request to a view in urls.py files
 | 
					## Django routes the request to a view in urls.py files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,7 +109,9 @@ show my message multiple times. PATCH is special--it can be
 | 
				
			|||||||
idempotent, and we like to write API endpoints in an idempotent fashion,
 | 
					idempotent, and we like to write API endpoints in an idempotent fashion,
 | 
				
			||||||
as much as possible.
 | 
					as much as possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This [cookbook](http://restcookbook.com/) and [tutorial](http://www.restapitutorial.com/) can be helpful if you are new to REST web applications.
 | 
					This [cookbook](http://restcookbook.com/) and
 | 
				
			||||||
 | 
					[tutorial](http://www.restapitutorial.com/) can be helpful if you are
 | 
				
			||||||
 | 
					new to REST web applications.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### PUT is only for creating new things
 | 
					### PUT is only for creating new things
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -137,7 +147,8 @@ In this way, the API is partially self-documenting.
 | 
				
			|||||||
The endpoints from the legacy JSON API are written without REST in
 | 
					The endpoints from the legacy JSON API are written without REST in
 | 
				
			||||||
mind. They are used extensively by the web client, and use POST.
 | 
					mind. They are used extensively by the web client, and use POST.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can see them in [zproject/legacy_urls.py](https://github.com/zulip/zulip/blob/master/zproject/legacy_urls.py).
 | 
					You can see them in
 | 
				
			||||||
 | 
					[zproject/legacy_urls.py](https://github.com/zulip/zulip/blob/master/zproject/legacy_urls.py).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Webhook integrations may not be RESTful
 | 
					### Webhook integrations may not be RESTful
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -147,23 +158,29 @@ only POST.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Django calls rest_dispatch for REST endpoints, and authenticates
 | 
					## Django calls rest_dispatch for REST endpoints, and authenticates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For requests that correspond to a REST url pattern, Zulip configures its
 | 
					For requests that correspond to a REST url pattern, Zulip configures
 | 
				
			||||||
url patterns (see [zerver/lib/rest.py](https://github.com/zulip/zulip/blob/master/zerver/lib/rest.py)) so that the action called is
 | 
					its url patterns (see
 | 
				
			||||||
`rest_dispatch`. This method will authenticate the user, either through
 | 
					[zerver/lib/rest.py](https://github.com/zulip/zulip/blob/master/zerver/lib/rest.py))
 | 
				
			||||||
a session token from a cookie, or from an `email:api-key` string given
 | 
					so that the action called is `rest_dispatch`. This method will
 | 
				
			||||||
via HTTP Basic Auth for API clients.
 | 
					authenticate the user, either through a session token from a cookie,
 | 
				
			||||||
 | 
					or from an `email:api-key` string given via HTTP Basic Auth for API
 | 
				
			||||||
 | 
					clients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It will then look up what HTTP verb was used (GET, POST, etc) to make
 | 
					It will then look up what HTTP verb was used (GET, POST, etc) to make
 | 
				
			||||||
the request, and then figure out which view to show from that.
 | 
					the request, and then figure out which view to show from that.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In our example,
 | 
					In our example,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
{'GET': 'zerver.views.users.get_members_backend',
 | 
					{'GET': 'zerver.views.users.get_members_backend',
 | 
				
			||||||
 'PUT': 'zerver.views.users.create_user_backend'}
 | 
					 'PUT': 'zerver.views.users.create_user_backend'}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
is supplied as an argument to `rest_dispatch`, along with the [HTTPRequest](https://docs.djangoproject.com/en/1.8/ref/request-response/).
 | 
					
 | 
				
			||||||
 | 
					is supplied as an argument to `rest_dispatch`, along with the
 | 
				
			||||||
 | 
					[HTTPRequest](https://docs.djangoproject.com/en/1.8/ref/request-response/).
 | 
				
			||||||
The request has the HTTP verb `PUT`, which `rest_dispatch` can use to
 | 
					The request has the HTTP verb `PUT`, which `rest_dispatch` can use to
 | 
				
			||||||
find the correct view to show: `zerver.views.users.create_user_backend`.
 | 
					find the correct view to show:
 | 
				
			||||||
 | 
					`zerver.views.users.create_user_backend`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## The view will authorize the user, extract request variables, and validate them
 | 
					## The view will authorize the user, extract request variables, and validate them
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -176,7 +193,9 @@ return `json_error` in the case of an error, which gives a JSON string:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
`{'result': 'error', 'msg': <some error message>}`
 | 
					`{'result': 'error', 'msg': <some error message>}`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
in a [HTTP Response](https://docs.djangoproject.com/en/1.8/ref/request-response/) with a content type of 'application/json'.
 | 
					in a
 | 
				
			||||||
 | 
					[HTTP Response](https://docs.djangoproject.com/en/1.8/ref/request-response/)
 | 
				
			||||||
 | 
					with a content type of 'application/json'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To pass back data from the server to the calling client, in the event of
 | 
					To pass back data from the server to the calling client, in the event of
 | 
				
			||||||
a successfully handled request, we use `json_success(data=<some python object which can be converted to a JSON string>`.
 | 
					a successfully handled request, we use `json_success(data=<some python object which can be converted to a JSON string>`.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,18 +16,29 @@ override that configuration).
 | 
				
			|||||||
If you want to use a remote Postgresql database, you should configure
 | 
					If you want to use a remote Postgresql database, you should configure
 | 
				
			||||||
the information about the connection with the server. You need a user
 | 
					the information about the connection with the server. You need a user
 | 
				
			||||||
called "zulip" in your database server. You can configure these
 | 
					called "zulip" in your database server. You can configure these
 | 
				
			||||||
options in /etc/zulip/settings.py:
 | 
					options in /etc/zulip/settings.py (the below descriptions are from the
 | 
				
			||||||
 | 
					Postgresql documentation):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* REMOTE_POSTGRES_HOST: Name or IP address of the remote host
 | 
					* REMOTE_POSTGRES_HOST: Name or IP address of the remote host
 | 
				
			||||||
* REMOTE_POSTGRES_SSLMODE: SSL Mode used to connect to the server, different options you can use are:
 | 
					* REMOTE_POSTGRES_SSLMODE: SSL Mode used to connect to the server,
 | 
				
			||||||
  * disable: I don't care about security, and I don't want to pay the overhead of encryption.
 | 
					  different options you can use are:
 | 
				
			||||||
  * allow: I don't care about security, but I will pay the overhead of encryption if the server insists on it.
 | 
					  * disable: I don't care about security, and I don't want to pay the
 | 
				
			||||||
  * prefer: I don't care about encryption, but I wish to pay the overhead of encryption if the server supports it.
 | 
					    overhead of encryption.
 | 
				
			||||||
  * require: I want my data to be encrypted, and I accept the overhead. I trust that the network will make sure I always connect to the server I want.
 | 
					  * allow: I don't care about security, but I will pay the overhead of
 | 
				
			||||||
  * verify-ca: I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server that I trust.
 | 
					    encryption if the server insists on it.
 | 
				
			||||||
  * verify-full: I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server I trust, and that it's the one I specify.
 | 
					  * prefer: I don't care about encryption, but I wish to pay the
 | 
				
			||||||
 | 
					    overhead of encryption if the server supports it.
 | 
				
			||||||
 | 
					  * require: I want my data to be encrypted, and I accept the
 | 
				
			||||||
 | 
					    overhead. I trust that the network will make sure I always connect
 | 
				
			||||||
 | 
					    to the server I want.
 | 
				
			||||||
 | 
					  * verify-ca: I want my data encrypted, and I accept the overhead. I
 | 
				
			||||||
 | 
					    want to be sure that I connect to a server that I trust.
 | 
				
			||||||
 | 
					  * verify-full: I want my data encrypted, and I accept the
 | 
				
			||||||
 | 
					    overhead. I want to be sure that I connect to a server I trust,
 | 
				
			||||||
 | 
					    and that it's the one I specify.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Then you should specify the password of the user zulip for the database in /etc/zulip/zulip-secrets.conf:
 | 
					Then you should specify the password of the user zulip for the
 | 
				
			||||||
 | 
					database in /etc/zulip/zulip-secrets.conf:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
postgres_password = xxxx
 | 
					postgres_password = xxxx
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -194,7 +194,9 @@ REQ also helps us with request variable validation. For example:
 | 
				
			|||||||
  integer (`converter` differs from `validator` in that it does not
 | 
					  integer (`converter` differs from `validator` in that it does not
 | 
				
			||||||
  automatically marshall the input from JSON).
 | 
					  automatically marshall the input from JSON).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
See [zerver/lib/validator.py](https://github.com/zulip/zulip/blob/master/zerver/lib/validator.py) for more validators and their documentation.
 | 
					See
 | 
				
			||||||
 | 
					[zerver/lib/validator.py](https://github.com/zulip/zulip/blob/master/zerver/lib/validator.py)
 | 
				
			||||||
 | 
					for more validators and their documentation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Deciding which HTTP verb to use
 | 
					### Deciding which HTTP verb to use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user